* linux-6.16/fs/jffs2/readinode.c:189: loop can never finish @ 2025-08-04 6:23 David Binderman 2025-08-04 7:10 ` Zhihao Cheng 0 siblings, 1 reply; 4+ messages in thread From: David Binderman @ 2025-08-04 6:23 UTC (permalink / raw) To: dwmw2@infradead.org, richard@nod.at, linux-mtd@lists.infradead.org, Linux Kernel Mailing List Hello there, Static analyser cppcheck said: linux-6.16/fs/jffs2/readinode.c:189:24: style: Expression is always true because 'else if' condition is opposite to previous condition at line 187. [multiCondition] Source code is while (next) { tn = rb_entry(next, struct jffs2_tmp_dnode_info, rb); if (tn->fn->ofs < offset) next = tn->rb.rb_right; else if (tn->fn->ofs >= offset) next = tn->rb.rb_left; else break; } It looks to me like this loop will never finish. Suggest change ">=" to ">". Regards David Binderman ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: linux-6.16/fs/jffs2/readinode.c:189: loop can never finish 2025-08-04 6:23 linux-6.16/fs/jffs2/readinode.c:189: loop can never finish David Binderman @ 2025-08-04 7:10 ` Zhihao Cheng 2025-08-04 7:30 ` David Oberhollenzer 0 siblings, 1 reply; 4+ messages in thread From: Zhihao Cheng @ 2025-08-04 7:10 UTC (permalink / raw) To: David Binderman, dwmw2@infradead.org, richard@nod.at, linux-mtd@lists.infradead.org, Linux Kernel Mailing List 在 2025/8/4 14:23, David Binderman 写道: > Hello there, > > Static analyser cppcheck said: > > linux-6.16/fs/jffs2/readinode.c:189:24: style: Expression is always true because 'else if' condition is opposite to previous condition at line 187. [multiCondition] > > Source code is > > while (next) { Hi, The 'next != NULL' is also a condition for the loop, this snippet of code finds a leaf node in 'tn_root'. > tn = rb_entry(next, struct jffs2_tmp_dnode_info, rb); > > if (tn->fn->ofs < offset) > next = tn->rb.rb_right; > else if (tn->fn->ofs >= offset) > next = tn->rb.rb_left; > else > break; > } > > It looks to me like this loop will never finish. > Suggest change ">=" to ">". > > Regards > > David Binderman > > > ______________________________________________________ > Linux MTD discussion mailing list > http://lists.infradead.org/mailman/listinfo/linux-mtd/ > . > ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: linux-6.16/fs/jffs2/readinode.c:189: loop can never finish 2025-08-04 7:10 ` Zhihao Cheng @ 2025-08-04 7:30 ` David Oberhollenzer 2025-08-04 10:54 ` David Woodhouse 0 siblings, 1 reply; 4+ messages in thread From: David Oberhollenzer @ 2025-08-04 7:30 UTC (permalink / raw) To: Zhihao Cheng, David Binderman, dwmw2@infradead.org, richard@nod.at, linux-mtd@lists.infradead.org, Linux Kernel Mailing List Hi, On 8/4/25 9:10 AM, Zhihao Cheng wrote: > > The 'next != NULL' is also a condition for the loop, this snippet of code finds a leaf node in 'tn_root'. Yes, this is a classic tree traversal. Assuming the tree isn't broken, the loop eventually terminates when it runs of a leaf. The real issue with this code is that this is the *only* exit condition of the loop. The traversal loop always branches until it hits a leaf and the function then returns NULL. I'm pretty sure this might not be the intended behavior. Greetings, David ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: linux-6.16/fs/jffs2/readinode.c:189: loop can never finish 2025-08-04 7:30 ` David Oberhollenzer @ 2025-08-04 10:54 ` David Woodhouse 0 siblings, 0 replies; 4+ messages in thread From: David Woodhouse @ 2025-08-04 10:54 UTC (permalink / raw) To: David Oberhollenzer, Zhihao Cheng, David Binderman, richard@nod.at, linux-mtd@lists.infradead.org, Linux Kernel Mailing List [-- Attachment #1.1: Type: text/plain, Size: 2967 bytes --] On Mon, 2025-08-04 at 09:30 +0200, David Oberhollenzer wrote: > Hi, > > On 8/4/25 9:10 AM, Zhihao Cheng wrote: > > > > The 'next != NULL' is also a condition for the loop, this snippet > > of code finds a leaf node in 'tn_root'. > > Yes, this is a classic tree traversal. Assuming the tree isn't > broken, the loop eventually terminates when it runs of a leaf. > > The real issue with this code is that this is the *only* exit > condition of the loop. The traversal loop always branches until > it hits a leaf and the function then returns NULL. I'm pretty > sure this might not be the intended behavior. It's going back almost two decades now but... This function is used only during the file system scan, when we scan the whole medium and initially fill a big bucket of data nodes to be subsequently processed and (mostly) eliminated due to overlap. It's allows for early elimination of completely overlapped nodes, to reduce memory usage. See https://git.kernel.org/torvalds/c/df8e96f39103a for more details. The jffs2_add_tn_to_tree() function calls jffs2_lookup_tn() to get a *starting* point, and then it backs up with rb_prev() until it finds the *first* node which is part of the overlapping set. Then, jffs2_add_tn_to_tree() iterates forward from that node until it has passed the end point of the node being added, looking for nodes which have been completely obsoleted and can be discarded early. If jffs2_lookup_tn() *did* always return NULL, that wouldn't actually cause a correctness problem, as all this is only an optimisation anyway. But I don't believe it does — it iterates until 'next' is NULL, but then returns the 'tn' whose left or right child was that 'next'. I think there might be a missed optimisation here though. Instead of using only the *starting* offset of the newly-added node, I think the jffs2_lookup_fn() function should also use the *end* offset of the newly-added node. And should only follow the tree down tn->rb.rb_right if the current tn->fn->ofs is lower than *that*. Otherwise I think we miss out on immediately discarding a newly- discovered node which is already completely obsoleted by a node that starts *earlier* than it. There's absolutely no good reason why this tmp_dnode code couldn't have fairly comprehensive unit and torture tests, and I think I'd want to have those before trying to do something like this to improve the optimisation... --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -184,7 +184,7 @@ static struct jffs2_tmp_dnode_info *jffs2_lookup_tn(struct rb_root *tn_root, uin while (next) { tn = rb_entry(next, struct jffs2_tmp_dnode_info, rb); - if (tn->fn->ofs < offset) + if (tn->fn->ofs + tn->fn->size < offset) next = tn->rb.rb_right; else if (tn->fn->ofs >= offset) next = tn->rb.rb_left; [-- Attachment #1.2: smime.p7s --] [-- Type: application/pkcs7-signature, Size: 5069 bytes --] [-- Attachment #2: Type: text/plain, Size: 144 bytes --] ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2025-08-04 11:13 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-08-04 6:23 linux-6.16/fs/jffs2/readinode.c:189: loop can never finish David Binderman 2025-08-04 7:10 ` Zhihao Cheng 2025-08-04 7:30 ` David Oberhollenzer 2025-08-04 10:54 ` David Woodhouse
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).