Re: Oops in minixfs_statfs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxx> 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@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux