From: Josh Boyer <jwboyer@redhat.com>
To: Bob Copeland <me@bobcopeland.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>,
linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org
Subject: Re: Oops in minixfs_statfs
Date: Tue, 16 Aug 2011 20:31:39 -0400 [thread overview]
Message-ID: <20110817003138.GF2227@zod.bos.redhat.com> (raw)
In-Reply-To: <CAEKwDSC+dKrNWnCZ+VSszuHZL3g=Upr8wSO32r5a8o9Ty0mtTg@mail.gmail.com>
On Tue, Aug 16, 2011 at 06:20:05PM -0400, Bob Copeland wrote:
> On Tue, Aug 16, 2011 at 12:48 PM, Josh Boyer <jwboyer@redhat.com> wrote:
> > it seems we're getting a negative number in this particular calculation
> > in fs/minix/bitmap.c, count_free:
> >
> > i = ((numbits - (numblocks-1) * bh->b_size * 8) / 16) * 2;
> [...]
> > I'm not familiar enough with minixfs to know what the above is trying to
> > actually accomplish. I instrumented that function a bit and here is
> > some data from the 3 filesytems in question:
>
> I don't know minix either but I'll take a shot. This is trying to
> count the number of bits in the free map for inodes or data blocks
> that don't fit in a full file system block.
>
> count_free takes 3 params:
> map - an array of buffer heads that represent the free map for a 'thingy'
> (thingy being the technical term for inode, or data block)
> numblocks - the number of blocks to scan
> numbits - the maximum-valued thingy
>
> So, for example, there might be 4800 inodes in the filesystem. That
> means there are 4800/8 = 600 bits to represent their in-use state,
> and supposing a buffer head represents a 512-byte buffer (bh->b_size=512),
> you would need two blocks to store that. numblocks in this hypothetical
> example is 2 and numbits is 4801.
Yep, I gathered that. In the real case, there are 7 blocks, and the
block size of the fs is 4096. Though numbits still seems to be "maximum
number of blocks" based on the value and what is being passed to
count_free.
> Here's some annotated code with uninteresting parts removed:
>
> Loop over all but the last block:
>
> for (i=0; i<numblocks-1; i++) {
> sum += nibblemap[bh->b_data[j] & 0xf]
> + nibblemap[(bh->b_data[j]>>4) & 0xf];
> }
>
> Since we're counting zero bits this is just computing hweight(~x)...
>
> if (numblocks==0 || !(bh=map[numblocks-1]))
> return(0);
>
> Lookout, bh is assigned in the conditional!
>
> Ok so bh is the last block which might not be full of thingys, so
> we only want to look at the part that has thingys and not the rest.
>
> numblocks - 1 * bh->b_size * 8 is the number of bits we've already
> looked at. We'll call it nthingys. numbits - nthingys is the number
> of bits we want to continue to look at. "(x / 16) * 2 is a fancy way
Yes, except here numbits - nthingys winds up being a negative number in
the failing case.
> of saying "x / 8" except the result is on 2-byte boundaries. So that's
> the number of bytes left to look at, except for up to 15 possible
> extra bits.
>
> i = ((numbits - (numblocks-1) * bh->b_size * 8) / 16) * 2;
> for (j=0; j<i; j++) {
> sum += nibblemap[bh->b_data[j] & 0xf]
> + nibblemap[(bh->b_data[j]>>4) & 0xf];
> }
And we blow up in here somewhere.
> And then count the remaining 15 bits by masking off whatever portion
> is less than numbits and doing some fancy u16 casting.
>
> i = numbits%16;
> if (i!=0) {
> i = *(__u16 *)(&bh->b_data[j]) | ~((1<<i) - 1);
> sum += nibblemap[i & 0xf] + nibblemap[(i>>4) & 0xf];
> sum += nibblemap[(i>>8) & 0xf] + nibblemap[(i>>12) & 0xf];
> }
>
> return(sum);
> }
>
> Does that help?
It helps me understand what the code is doing a bit better, yes. Thank
you for that. Unfortunately, it doesn't really tell me why we get a
negative number in this case, and if we should be checking for that here
and what to do about it.
josh
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
next prev parent reply other threads:[~2011-08-17 0:32 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-08-16 16:48 Oops in minixfs_statfs Josh Boyer
2011-08-16 22:20 ` Bob Copeland
2011-08-17 0:31 ` Josh Boyer [this message]
2011-08-17 2:18 ` Al Viro
2011-08-17 3:12 ` Bob Copeland
2011-08-17 17:18 ` Josh Boyer
2011-08-18 21:13 ` Josh Boyer
2011-08-18 21:16 ` Al Viro
2011-08-18 22:24 ` Josh Boyer
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=20110817003138.GF2227@zod.bos.redhat.com \
--to=jwboyer@redhat.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=me@bobcopeland.com \
--cc=viro@zeniv.linux.org.uk \
/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).