Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 27 Sep 2005 21:54:32 +1000 (EST)
From:      Bruce Evans <bde@zeta.org.au>
To:        Mikhail Teterin <mi+mx@aldan.algebra.com>
Cc:        gayn.winters@bristolsystems.com, fs@FreeBSD.org
Subject:   Re: can not mount a large FAT32 filesystem
Message-ID:  <20050927201946.C24713@delplex.bde.org>
In-Reply-To: <200509261654.01697.mi%2Bmx@aldan.algebra.com>
References:  <02b301c5c2ba$4b2b9460$c901a8c0@workdog> <200509261654.01697.mi%2Bmx@aldan.algebra.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On Mon, 26 Sep 2005, Mikhail Teterin wrote:

> This is a flash card (Hitachi microdrive) inserted into a USB flash-reader.
> There is no BIOS.
>
> Not only does the card work fine in the camera (which formatted it), but
> Windows has no problems with it either. I'd rather help fix our FAT32
> support, than find a work-around...
>
> Is anyone on fs@ interested? The original symptomps and Gayn's comments are
> attached. Thanks!

Attachment is even better than top posting inhibiting replies, although not
as good as a url.

%% > I have a 4Gb flash-card with FAT32 filesystem. Whenever I try to mount
%% > it (on 5.x and 4.x) I get:
%% > 
%% > 	msdos: /dev/da0s1: Invalid argument

(It should actually say "msdosfs" in 5.x.  This renaming mainly breaks
compatibility.)  mount(8)'s error reporting is bad.  The EINVAL error
here is not completely obscure -- it normally means that the file system
is invalid, but the error for msdosfs vs msdos is very obscure -- IIRC
it is ENOENT meaning that the module for the file system wasn't found,
but mount(8) reports this as mount_msdos[fs] not being found despite
this mount utility being present.

%% > and the kernel complains:
%% > 
%% > 	da0: reading primary partition table: error reading fsbn 0

I think this error message is only printed by 4.x.  While error messages
printed using diskerr() are much better than their replacements in 5+.x,
this one is unfortunately missing the low-level error code so it is hard
to tell why the read failed.

%% > 	mountmsdosfs(): bad FAT32 filesystem

This error seems to be unrelated.  (I don't know how msdosfs got this
far, since the previous error is for the whole disk and should be fatal
-- see below.) The code in msdosfs in 4.x for this is:

% 	if (pmp->pm_RootDirEnts == 0) {
% 		if (bsp->bs710.bsBootSectSig2 != BOOTSIG2
% 		    || bsp->bs710.bsBootSectSig3 != BOOTSIG3
% 		    || pmp->pm_Sectors
% 		    || pmp->pm_FATsecs
% 		    || getushort(b710->bpbFSVers)) {
% 			error = EINVAL;
% 			printf("mountmsdosfs(): bad FAT32 filesystem\n");
% 			goto error_exit;
% 		}
% 		pmp->pm_fatmask = FAT32_MASK;
% 		pmp->pm_fatmult = 4;
% 		pmp->pm_fatdiv = 1;
% 		pmp->pm_FATsecs = getulong(b710->bpbBigFATsecs);
% 		if (getushort(b710->bpbExtFlags) & FATMIRROR)
% 			pmp->pm_curfat = getushort(b710->bpbExtFlags) & FATNUM;
% 		else
% 			pmp->pm_flags |= MSDOSFS_FATMIRROR;
% 	} else
% 		pmp->pm_flags |= MSDOSFS_FATMIRROR;

The file system's boot block passed several checks before here; in particular
it must have been readable.  Apparently (pmp->pm_RootDirEnts == 0) implies
FAT32 and then one of the other checks fails.  If it weren't for the error
reading sector 0, I would expect just a minor compatibility problem here.

%% > The method works with smaller cards in the same card-reader. This card
%% > works fine inside the camera, and I can get the pictures via. PTP
%% > protocol using gphoto.
%% > 
%% > Fdisk da0 says:
%% > 
%% > 	******* Working on device /dev/da0 *******
%% > 	parameters extracted from in-core disklabel are:
%% > 	cylinders=7936 heads=16 sectors/track=63 (1008 blks/cyl)
%% > 
%% > 	Figures below won't work with BIOS for partitions not in cyl 1
%% > 	parameters to be used for BIOS calculations are:
%% > 	cylinders=7936 heads=16 sectors/track=63 (1008 blks/cyl)
%% > 
%% > 	Media sector size is 512
%% > 	Warning: BIOS sector numbering starts with sector 1
%% > 	Information from DOS bootblock is:
%% > 	The data for partition 1 is:
%% > 	sysid 12,(DOS or Windows 95 with 32 bit FAT, LBA)
%% > 	    start 63, size 7998417 (3905 Meg), flag 80 (active)
%% > 		beg: cyl 0/ head 1/ sector 1;
%% > 		end: cyl 766/ head 15/ sector 63

I don't know how fdisk managed to read the MBR, since the kernel
couldn't.  There seem to be no "geometry" problems here.  63
sectors/track is normal.  16 heads only works with not-very-old BIOSes,
since it gives more than 1024 cylinders, but the card is new so it may
assume a not-very-old  BIOS).  The ending head number in the partition
entry matches 16 heads.  The star and size match the starting and ending
C/H/S (C matches mod 1024).  For some reason, the last complete cylinder
isn't used, and for the usual reasons, the 1 sector following the last
complete cylinder isn't used.

%% > Disklabel da0 says:
%% > 
%% > 	# /dev/da0:
%% > 	type: SCSI
%% > 	disk: SanDisk 
%% > 	label: ImageMate II 
%% > 	flags:
%% > 	bytes/sector: 512
%% > 	sectors/track: 63
%% > 	tracks/cylinder: 16
%% > 	sectors/cylinder: 1008
%% > 	cylinders: 7936
%% > 	sectors/unit: 7999489
%% > ...

This is consistent with the fdisk output.

%% Perhaps someone else can help sort this out better than I can, but I do
%% note that fdisk doesn't seem to be using the last (logical) cylinder,
%% because it reports using 7998417 + 63 = 7998480 sectors which is exactly
%% 1008 sectors less than 7936 cylinders * 1008 sectors/cylinder = 7999488
%% sectors.  (Why disklabel reports one more sector 7999489 is a mystery to
%% me.)

Disklabel probably reports 7999489 sectors because that is the actual
number of sectors.  Remember that the geometry of H=16/S=63 is invented.
16*63 just happens not to divide 7999489 evenly.  It seems to be normal
for ATA disks for the number of sectors to be dumbed down so that it is
a multiple of H*S, but this is a SCSI disk.

%% Assuming your BIOS supports LBA, you could try (back up first of course)
%% using fdisk to rewrite the label, or use fdisk to use all the logical
%% cylinders on the card.  Also, since you are not trying to boot from the
%% card, having it marked Active is unnecessary at best.

This probably won't help.

In 4.x, the initial error is from subr_diskmbr.c:

% 	mbr_offset = DOSBBSECTOR;
% reread_mbr:
% 	/* Read master boot record. */
% 	bp = geteblk((int)lp->d_secsize);
% 	bp->b_dev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART);
% 	bp->b_blkno = mbr_offset;
% 	bp->b_bcount = lp->d_secsize;
% 	bp->b_flags |= B_READ;
% 	BUF_STRATEGY(bp, 1);
% 	if (biowait(bp) != 0) {
% 		diskerr(bp, "reading primary partition table: error",
% 		    LOG_PRINTF, 0, (struct disklabel *)NULL);
% 		printf("\n");
% 		error = EIO;
% 		goto done;
% 	}
% ...
% done:
% 	bp->b_flags |= B_INVAL | B_AGE;
% 	brelse(bp);
% 	if (error == EINVAL)
% 		error = 0;
% 	return (error);
% }

It is hard to see how this causes the observed symptoms.  An error here
seems most likely to be caused by the sector size being wrong, but should
prevent all opens of the disk.  But we know that both fdisk(8) and the
start of msdosfs mount can open and read the disk.  fdisk opens the whole
disk and sees normal things.  msdosfs mount should be opening slice s1,
and that is more likely to not work than opening the whole disk.  Certainly
the above error prevents slice s1 being correctly located, so msdosfs
mount shouldn't see normal things.  But we know that msdosfs sees some
normal things before it sees a problem.

Try reading slice s1 using dd.  I would expect this to fail.

Bruce



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20050927201946.C24713>