} else { pmp->pm_fatentrysize = 16; pmp->pm_fatblocksize = MAXBSIZE; } #else	 if (FAT12(pmp))  pmp->pm_fatblocksize = 3 * pmp->pm_BytesPerSec; else  pmp->pm_fatblocksize = MAXBSIZE; #endif
else pmp->pm_fatblocksize = MAXBSIZE;
msdosfs_mountfs(devvp, mp, p)	struct vnode *devvp;	struct mount *mp;	struct proc *p;{	struct msdosfsmount *pmp;	struct buf *bp;	dev_t dev = devvp->v_rdev;	struct partinfo dpart;	union bootsector *bsp;	struct byte_bpb33 *b33;	struct byte_bpb50 *b50;	extern struct vnode *rootvp;	u_int8_t SecPerClust;	int	ronly, error;#ifdef	atari	int	bsize, dtype, tmp;#endif	/* !atari */	/*	 * Disallow multiple mounts of the same device.	 * Disallow mounting of a device that is currently in use	 * (except for root, which might share swap device for miniroot).	 * Flush out any old buffers remaining from a previous use.	 */	if (error = vfs_mountedon(devvp))		return (error);	if (vcount(devvp) > 1 && devvp != rootvp)		return (EBUSY);	if (error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0))		return (error);	ronly = (mp->mnt_flag & MNT_RDONLY) != 0;	if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p))		return (error);#ifdef	atari	bp  = NULL; /* both used in error_exit */	pmp = NULL;	/*	 * We need the disklabel to calculate the size of a FAT entry later on.	 * Also make sure the partition contains a filesystem of type FS_MSDOS.	 * This doesn't work for floppies, so we have to check for them too.	 *	 * At least some parts of the msdos fs driver seem to assume that the	 * size of a disk block will always be 512 bytes. Let's check it...	 */	if (error = VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p))		goto error_exit;	tmp   = dpart.part->p_fstype;	dtype = dpart.disklab->d_type;	bsize = dpart.disklab->d_secsize;	if (bsize != 512 || (dtype != DTYPE_FLOPPY && tmp != FS_MSDOS)) {		error = EINVAL;		goto error_exit;	}#else	/* !atari */	/*	 * Read the boot sector of the filesystem, and then check the boot	 * signature.  If not a dos boot sector then error out.	 */	bp = NULL;	pmp = NULL;#endif	/* !atari */	if (error = bread(devvp, 0, 512, NOCRED, &bp))		goto error_exit;	bp->b_flags |= B_AGE;	bsp = (union bootsector *)bp->b_data;	b33 = (struct byte_bpb33 *)bsp->bs33.bsBPB;	b50 = (struct byte_bpb50 *)bsp->bs50.bsBPB;#ifdef MSDOSFS_CHECKSIG	if (bsp->bs50.bsBootSectSig != BOOTSIG) {		error = EINVAL;		goto error_exit;	}#endif	pmp = malloc(sizeof *pmp, M_MSDOSFSMNT, M_WAITOK);	bzero((caddr_t)pmp, sizeof *pmp);	pmp->pm_mountp = mp;	/*	 * Compute several useful quantities from the bpb in the	 * bootsector.  Copy in the dos 5 variant of the bpb then fix up	 * the fields that are different between dos 5 and dos 3.3.	 */	SecPerClust = b50->bpbSecPerClust;	pmp->pm_BytesPerSec = getushort(b50->bpbBytesPerSec);	pmp->pm_ResSectors = getushort(b50->bpbResSectors);	pmp->pm_FATs = b50->bpbFATs;	pmp->pm_RootDirEnts = getushort(b50->bpbRootDirEnts);	pmp->pm_Sectors = getushort(b50->bpbSectors);	pmp->pm_FATsecs = getushort(b50->bpbFATsecs);#ifdef	atari	/*	 * Meaningless on  a gemdos fs. This kind of information	 * should be extracted from the disklabel structure.	 */	pmp->pm_SecPerTrack = 1;	/* anything between 1 and  63 */	pmp->pm_Heads = 1;		/* anything between 1 and 255 */	pmp->pm_Media = 0;		/* unused, any value will do  */#else	/* !atari */	pmp->pm_SecPerTrack = getushort(b50->bpbSecPerTrack);	pmp->pm_Heads = getushort(b50->bpbHeads);	pmp->pm_Media = b50->bpbMedia;	/* XXX - We should probably check more values here */    	if (!pmp->pm_BytesPerSec || !SecPerClust ||	    pmp->pm_Heads > 255 || pmp->pm_SecPerTrack > 63) {		error = EINVAL;		goto error_exit;	}#endif	/* !atari */	if (pmp->pm_Sectors == 0) {		pmp->pm_HiddenSects = getulong(b50->bpbHiddenSecs);		pmp->pm_HugeSectors = getulong(b50->bpbHugeSectors);	} else {		pmp->pm_HiddenSects = getushort(b33->bpbHiddenSecs);		pmp->pm_HugeSectors = pmp->pm_Sectors;	}#ifdef	atari	/*	 * Check a few values (could do some more):	 * - logical sector size: power of 2, >= block size	 * - sectors per cluster: power of 2, >= 1	 * - number of sectors:   >= 1, <= size of partition	 */	if ( pmp->pm_BytesPerSec < bsize	  || pmp->pm_BytesPerSec & (pmp->pm_BytesPerSec - 1)	  || !SecPerClust	  || SecPerClust & (SecPerClust - 1)	  || !pmp->pm_HugeSectors	  || pmp->pm_HugeSectors * pmp->pm_BytesPerSec				> dpart.part->p_size * bsize) {		error = EINVAL;		goto error_exit;	}	/*	 * XXX - Many parts of the msdos fs driver seem to assume that	 * the number of bytes per logical sector (BytesPerSec) will	 * always be the same as the number of bytes per disk block	 * Let's pretend it is.	 */	tmp = pmp->pm_BytesPerSec / bsize;	pmp->pm_BytesPerSec = bsize;	pmp->pm_HugeSectors *= tmp;	pmp->pm_HiddenSects *= tmp;	pmp->pm_ResSectors *= tmp;	pmp->pm_Sectors *= tmp;	pmp->pm_FATsecs *= tmp;#endif	/* atari */	pmp->pm_fatblk = pmp->pm_ResSectors;	pmp->pm_rootdirblk = pmp->pm_fatblk +	    (pmp->pm_FATs * pmp->pm_FATsecs);	pmp->pm_rootdirsize = (pmp->pm_RootDirEnts * sizeof(struct direntry)	    + pmp->pm_BytesPerSec - 1)	    / pmp->pm_BytesPerSec;/* in sectors */	pmp->pm_firstcluster = pmp->pm_rootdirblk + pmp->pm_rootdirsize;	pmp->pm_nmbrofclusters = (pmp->pm_HugeSectors - pmp->pm_firstcluster) /	    SecPerClust;	pmp->pm_maxcluster = pmp->pm_nmbrofclusters + 1;	pmp->pm_fatsize = pmp->pm_FATsecs * pmp->pm_BytesPerSec;#ifdef	atari	if (dtype == DTYPE_FLOPPY) {		pmp->pm_fatentrysize = 12;		pmp->pm_fatblocksize = 3 * pmp->pm_BytesPerSec;	} else {		pmp->pm_fatentrysize = 16;		pmp->pm_fatblocksize = MAXBSIZE;	}#else	/* !atari */	if (FAT12(pmp))		/*		 * This will usually be a floppy disk. This size makes sure		 * that one fat entry will not be split across multiple		 * blocks.		 */		pmp->pm_fatblocksize = 3 * pmp->pm_BytesPerSec;	else		/*		 * This will usually be a hard disk. Reading or writing one		 * block should be quite fast.		 */		pmp->pm_fatblocksize = MAXBSIZE;#endif	/* !atari */	pmp->pm_fatblocksec = pmp->pm_fatblocksize / pmp->pm_BytesPerSec;	pmp->pm_bnshift = ffs(pmp->pm_BytesPerSec) - 1;	/*	 * Compute mask and shift value for isolating cluster relative byte	 * offsets and cluster numbers from a file offset.	 */	pmp->pm_bpcluster = SecPerClust * pmp->pm_BytesPerSec;	pmp->pm_crbomask = pmp->pm_bpcluster - 1;	pmp->pm_cnshift = ffs(pmp->pm_bpcluster) - 1;#ifdef	atari	/*	 * We already know that the number of sectors per cluster is	 * > 0 and a power of 2.	 */#else	/* !atari */	/*	 * Check for valid cluster size	 * must be a power of 2	 */	if (pmp->pm_bpcluster ^ (1 << pmp->pm_cnshift)) {		error = EINVAL;		goto error_exit;	}#endif	/* !atari */	/*	 * Release the bootsector buffer.	 */	brelse(bp);	bp = NULL;	/*	 * Allocate memory for the bitmap of allocated clusters, and then	 * fill it in.	 */	pmp->pm_inusemap = malloc(((pmp->pm_maxcluster + N_INUSEBITS - 1)				   / N_INUSEBITS)				  * sizeof(*pmp->pm_inusemap),				  M_MSDOSFSFAT, M_WAITOK);	/*	 * fillinusemap() needs pm_devvp.	 */	pmp->pm_dev = dev;	pmp->pm_devvp = devvp;	/*	 * Have the inuse map filled in.	 */	if (error = fillinusemap(pmp))		goto error_exit;	/*	 * If they want fat updates to be synchronous then let them suffer	 * the performance degradation in exchange for the on disk copy of	 * the fat being correct just about all the time.  I suppose this	 * would be a good thing to turn on if the kernel is still flakey.	 */	if (mp->mnt_flag & MNT_SYNCHRONOUS)		pmp->pm_flags |= MSDOSFSMNT_WAITONFAT;	/*	 * Finish up.	 */	if (ronly)		pmp->pm_flags |= MSDOSFSMNT_RONLY;	else		pmp->pm_fmod = 1;	mp->mnt_data = (qaddr_t)pmp;        mp->mnt_stat.f_fsid.val[0] = (long)dev;        mp->mnt_stat.f_fsid.val[1] = makefstype(MOUNT_MSDOS);	mp->mnt_flag |= MNT_LOCAL;#ifdef QUOTA	/*	 * If we ever do quotas for DOS filesystems this would be a place	 * to fill in the info in the msdosfsmount structure. You dolt,	 * quotas on dos filesystems make no sense because files have no	 * owners on dos filesystems. of course there is some empty space	 * in the directory entry where we could put uid's and gid's.	 */#endif	devvp->v_specflags |= SI_MOUNTEDON;	return (0);error_exit:;	if (bp)		brelse(bp);	(void) VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p);	if (pmp) {		if (pmp->pm_inusemap)			free(pmp->pm_inusemap, M_MSDOSFSFAT);		free(pmp, M_MSDOSFSMNT);		mp->mnt_data = (qaddr_t)0;	}	return (error);}