linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: David Woodhouse <dwmw2@infradead.org>
To: David Oberhollenzer <david.oberhollenzer@sigma-star.at>,
	Zhihao Cheng <chengzhihao1@huawei.com>,
	David Binderman <dcb314@hotmail.com>,
	 "richard@nod.at" <richard@nod.at>,
	"linux-mtd@lists.infradead.org" <linux-mtd@lists.infradead.org>,
	Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
Subject: Re: linux-6.16/fs/jffs2/readinode.c:189: loop can never finish
Date: Mon, 04 Aug 2025 11:54:47 +0100	[thread overview]
Message-ID: <6f3dbdc7368ba5d1bcc7bcf4e31a53b8b71904a4.camel@infradead.org> (raw)
In-Reply-To: <8114ae51-a238-40d3-9ecd-70e23abae28b@sigma-star.at>

[-- Attachment #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 #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 5069 bytes --]

      reply	other threads:[~2025-08-04 10:54 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=6f3dbdc7368ba5d1bcc7bcf4e31a53b8b71904a4.camel@infradead.org \
    --to=dwmw2@infradead.org \
    --cc=chengzhihao1@huawei.com \
    --cc=david.oberhollenzer@sigma-star.at \
    --cc=dcb314@hotmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mtd@lists.infradead.org \
    --cc=richard@nod.at \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).