mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-18 06:14:27 +00:00
Add a "-o large" mount option for msdosfs. Convert compile-time checks for
#ifdef MSDOSFS_LARGE to run-time checks to see if "-o large" was specified. Test case provided by Oliver Fromme: truncate -s 200G test.img mdconfig -a -t vnode -f test.img -u 9 newfs_msdos -s 419430400 -n 1 /dev/md9 zip250 mount -t msdosfs /dev/md9 /mnt # should fail mount -t msdosfs -o large /dev/md9 /mnt # should succeed PR: 105964 Requested by: Oliver Fromme <olli lurza secnetix de> Tested by: trhodes MFC after: 2 weeks
This commit is contained in:
parent
25777ce331
commit
f458f2a553
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=166340
|
@ -1106,7 +1106,7 @@ fs/hpfs/hpfs_vnops.c optional hpfs
|
|||
fs/msdosfs/msdosfs_conv.c optional msdosfs
|
||||
fs/msdosfs/msdosfs_denode.c optional msdosfs
|
||||
fs/msdosfs/msdosfs_fat.c optional msdosfs
|
||||
fs/msdosfs/msdosfs_fileno.c optional msdosfs_large
|
||||
fs/msdosfs/msdosfs_fileno.c optional msdosfs
|
||||
fs/msdosfs/msdosfs_iconv.c optional msdosfs_iconv
|
||||
fs/msdosfs/msdosfs_lookup.c optional msdosfs
|
||||
fs/msdosfs/msdosfs_vfsops.c optional msdosfs
|
||||
|
|
|
@ -83,7 +83,7 @@ static const char *msdosfs_opts[] = {
|
|||
"export", "force", "sync",
|
||||
"uid", "gid", "mask", "dirmask",
|
||||
"shortname", "shortnames", "longname", "longnames", "nowin95", "win95",
|
||||
"kiconv", "cs_win", "cs_dos", "cs_local",
|
||||
"kiconv", "cs_win", "cs_dos", "cs_local", "large",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -466,6 +466,21 @@ mountmsdosfs(devvp, mp, td)
|
|||
pmp->pm_cp = cp;
|
||||
pmp->pm_bo = bo;
|
||||
|
||||
/*
|
||||
* Experimental support for large MS-DOS filesystems.
|
||||
* WARNING: This uses at least 32 bytes of kernel memory (which is not
|
||||
* reclaimed until the FS is unmounted) for each file on disk to map
|
||||
* between the 32-bit inode numbers used by VFS and the 64-bit
|
||||
* pseudo-inode numbers used internally by msdosfs. This is only
|
||||
* safe to use in certain controlled situations (e.g. read-only FS
|
||||
* with less than 1 million files).
|
||||
* Since the mappings do not persist across unmounts (or reboots), these
|
||||
* filesystems are not suitable for exporting through NFS, or any other
|
||||
* application that requires fixed inode numbers.
|
||||
*/
|
||||
vfs_flagopt(mp->mnt_optnew, "large", &pmp->pm_flags,
|
||||
MSDOSFS_LARGEFS);
|
||||
|
||||
/*
|
||||
* Compute several useful quantities from the bpb in the
|
||||
* bootsector. Copy in the dos 5 variant of the bpb then fix up
|
||||
|
@ -508,19 +523,20 @@ mountmsdosfs(devvp, mp, td)
|
|||
pmp->pm_HiddenSects = getushort(b33->bpbHiddenSecs);
|
||||
pmp->pm_HugeSectors = pmp->pm_Sectors;
|
||||
}
|
||||
#ifndef MSDOSFS_LARGE
|
||||
if (pmp->pm_HugeSectors > 0xffffffff /
|
||||
(pmp->pm_BytesPerSec / sizeof(struct direntry)) + 1) {
|
||||
/*
|
||||
* We cannot deal currently with this size of disk
|
||||
* due to fileid limitations (see msdosfs_getattr and
|
||||
* msdosfs_readdir)
|
||||
*/
|
||||
error = EINVAL;
|
||||
printf("mountmsdosfs(): disk too big, sorry\n");
|
||||
goto error_exit;
|
||||
if (!(pmp->pm_flags & MSDOSFS_LARGEFS)) {
|
||||
if (pmp->pm_HugeSectors > 0xffffffff /
|
||||
(pmp->pm_BytesPerSec / sizeof(struct direntry)) + 1) {
|
||||
/*
|
||||
* We cannot deal currently with this size of disk
|
||||
* due to fileid limitations (see msdosfs_getattr and
|
||||
* msdosfs_readdir)
|
||||
*/
|
||||
error = EINVAL;
|
||||
vfs_mount_error(mp,
|
||||
"Disk too big, try '-o large' mount option");
|
||||
goto error_exit;
|
||||
}
|
||||
}
|
||||
#endif /* !MSDOSFS_LARGE */
|
||||
|
||||
if (pmp->pm_RootDirEnts == 0) {
|
||||
if (pmp->pm_Sectors
|
||||
|
@ -721,9 +737,8 @@ mountmsdosfs(devvp, mp, td)
|
|||
mp->mnt_flag |= MNT_LOCAL;
|
||||
MNT_IUNLOCK(mp);
|
||||
|
||||
#ifdef MSDOSFS_LARGE
|
||||
msdosfs_fileno_init(mp);
|
||||
#endif
|
||||
if (pmp->pm_flags & MSDOSFS_LARGEFS)
|
||||
msdosfs_fileno_init(mp);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -806,9 +821,9 @@ msdosfs_unmount(mp, mntflags, td)
|
|||
PICKUP_GIANT();
|
||||
vrele(pmp->pm_devvp);
|
||||
free(pmp->pm_inusemap, M_MSDOSFSFAT);
|
||||
#ifdef MSDOSFS_LARGE
|
||||
msdosfs_fileno_free(mp);
|
||||
#endif
|
||||
if (pmp->pm_flags & MSDOSFS_LARGEFS) {
|
||||
msdosfs_fileno_free(mp);
|
||||
}
|
||||
free(pmp, M_MSDOSFSMNT);
|
||||
mp->mnt_data = (qaddr_t)0;
|
||||
MNT_ILOCK(mp);
|
||||
|
|
|
@ -326,11 +326,12 @@ msdosfs_getattr(ap)
|
|||
fileid = (uint64_t)roottobn(pmp, 0) * dirsperblk;
|
||||
fileid += (uint64_t)dep->de_diroffset / sizeof(struct direntry);
|
||||
}
|
||||
#ifdef MSDOSFS_LARGE
|
||||
vap->va_fileid = msdosfs_fileno_map(pmp->pm_mountp, fileid);
|
||||
#else
|
||||
vap->va_fileid = (long)fileid;
|
||||
#endif
|
||||
|
||||
if (pmp->pm_flags & MSDOSFS_LARGEFS)
|
||||
vap->va_fileid = msdosfs_fileno_map(pmp->pm_mountp, fileid);
|
||||
else
|
||||
vap->va_fileid = (long)fileid;
|
||||
|
||||
if ((dep->de_Attributes & ATTR_READONLY) == 0)
|
||||
mode = S_IRWXU|S_IRWXG|S_IRWXO;
|
||||
else
|
||||
|
@ -1571,12 +1572,14 @@ msdosfs_readdir(ap)
|
|||
* dirsperblk;
|
||||
else
|
||||
fileno = 1;
|
||||
#ifdef MSDOSFS_LARGE
|
||||
dirbuf.d_fileno = msdosfs_fileno_map(
|
||||
pmp->pm_mountp, fileno);
|
||||
#else
|
||||
dirbuf.d_fileno = (uint32_t)fileno;
|
||||
#endif
|
||||
if (pmp->pm_flags & MSDOSFS_LARGEFS) {
|
||||
dirbuf.d_fileno =
|
||||
msdosfs_fileno_map(pmp->pm_mountp,
|
||||
fileno);
|
||||
} else {
|
||||
|
||||
dirbuf.d_fileno = (uint32_t)fileno;
|
||||
}
|
||||
dirbuf.d_type = DT_DIR;
|
||||
switch (n) {
|
||||
case 0:
|
||||
|
@ -1700,12 +1703,12 @@ msdosfs_readdir(ap)
|
|||
fileno = (uint64_t)offset / sizeof(struct direntry);
|
||||
dirbuf.d_type = DT_REG;
|
||||
}
|
||||
#ifdef MSDOSFS_LARGE
|
||||
dirbuf.d_fileno = msdosfs_fileno_map(pmp->pm_mountp,
|
||||
fileno);
|
||||
#else
|
||||
dirbuf.d_fileno = (uint32_t)fileno;
|
||||
#endif
|
||||
if (pmp->pm_flags & MSDOSFS_LARGEFS) {
|
||||
dirbuf.d_fileno =
|
||||
msdosfs_fileno_map(pmp->pm_mountp, fileno);
|
||||
} else
|
||||
dirbuf.d_fileno = (uint32_t)fileno;
|
||||
|
||||
if (chksum != winChksum(dentp)) {
|
||||
dirbuf.d_namlen = dos2unixfn(dentp->deName,
|
||||
(u_char *)dirbuf.d_name,
|
||||
|
|
Loading…
Reference in a new issue