Re: newfs_msdos and DVD-RAM

From: Andriy Gapon <avg_at_freebsd.org>
Date: Mon, 29 Mar 2010 15:42:59 +0300
If you want to make sure that I see your reply please include me into recipient
list.  FreeBSD mailing lists sometimes have high volume and it's easy to miss a
followup even if you are interested in reading it.

on 28/03/2010 18:25 Fabian Keil said the following:
> Andriy Gapon <avg_at_icyb.net.ua> wrote:
>> Looking at the code in mountmsdosfs(), it seems that SecPerClust can
>> have zero value at the place of the crash only if pm_BlkPerSec is zero.
>> See this line and the check above it:
>> SecPerClust         *= pmp->pm_BlkPerSec;
>> But that is impossible because of the same if statement.
>>
>> In my opinion, the only possible explanation is an overflow of a
>> SecPerClust value.  Given that its type is u_int8_t, it seems plausible.
> 
> That seems to be indeed the case. Adding a printf before
> 	SecPerClust         *= pmp->pm_BlkPerSec;
> 
> Results in: Multiplying 64 with 8

Interesting.  See below.

> Using an unsigned int for SecPerClust allows to mount the file
> system and df -h correctly shows its size, but cd'ing into it
> and running ls -l leads to another panic:

I that this local workaround cures only one local symptom and pushes the problem
further in the code.  The panic you got is a symptom of a deeper issue.

Could you please remind us in what way was the filesystem created?
Was it FreeBSD newfs_msdos?

I am not a FAT expert and I know to take Wikipedia with a grain of salt.
But please take a look at this:
http://en.wikipedia.org/wiki/File_Allocation_Table#Boot_Sector

In our formula:
SecPerClust         *= pmp->pm_BlkPerSec;
we have the following parameters:
SecPerClust[in] - sectors per cluster
pm_BlkPerSec - bytes per sector divided by 512 (pm_BytesPerSec / DEV_BSIZE)
SecPerClust[out] - bytes per cluster divided by 512

So we have:
sectors per cluster: 64
bytes per sector: 4096

That Wikipedia article says: "However, the value must not be such that the number
of bytes per cluster becomes greater than 32 KB."
But in our case it's 256K, the same value that is passed as 'size' parameter to
bread() in the crash stack trace below.

By the way, that 32KB limit means that value of SecPerClust[out] should never be
greater than 64 and SecPerClust[in] is limited to 128, so its current must be of
sufficient size to hold all allowed values.

Thus, clearly, it is a fault of a tool that formatted the media for FAT.
It should have picked correct values, or rejected incorrect values if those were
provided as overrides via command line options.

> fk_at_r500 /usr/crash $kgdb kernel.1/kernel.symbols vmcore.1
[snip]
> Unread portion of the kernel message buffer:
> panic: getblk: size(262144) > MAXBSIZE(65536)
[snip]
> #11 0xffffffff803bedfb in panic (fmt=Variable "fmt" is not available.
> ) at /usr/src/sys/kern/kern_shutdown.c:562
> #12 0xffffffff8042ecde in getblk (vp=0xffffff006dbfad20, blkno=992, size=262144, slpflag=0, slptimeo=Variable "slptimeo" is not available.
> ) at /usr/src/sys/kern/vfs_bio.c:2523
> #13 0xffffffff8042f12f in breadn (vp=0xffffff006dbfad20, blkno=Variable "blkno" is not available.
> ) at /usr/src/sys/kern/vfs_bio.c:800
> #14 0xffffffff8042f24e in bread (vp=Variable "vp" is not available.
> ) at /usr/src/sys/kern/vfs_bio.c:748
> #15 0xffffffff8035efc2 in msdosfs_readdir (ap=0xffffff803e71ca60) at /usr/src/sys/fs/msdosfs/msdosfs_vnops.c:1641
[snip]

-- 
Andriy Gapon
Received on Mon Mar 29 2010 - 10:43:04 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:40:02 UTC