summaryrefslogtreecommitdiffstats
path: root/sys/fs
diff options
context:
space:
mode:
authorrodrigc <rodrigc@FreeBSD.org>2007-01-30 03:11:45 +0000
committerrodrigc <rodrigc@FreeBSD.org>2007-01-30 03:11:45 +0000
commitfdf518fe9a7942b309ce0ea9424e5670fcdf27c3 (patch)
treedcfa8a8ce70fbf1c51e450b21d8310fa37f311d1 /sys/fs
parentbbf865842dfb6c8311e7d908ea1c1a6bdb4eb103 (diff)
downloadFreeBSD-src-fdf518fe9a7942b309ce0ea9424e5670fcdf27c3.zip
FreeBSD-src-fdf518fe9a7942b309ce0ea9424e5670fcdf27c3.tar.gz
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
Diffstat (limited to 'sys/fs')
-rw-r--r--sys/fs/msdosfs/msdosfs_vfsops.c53
-rw-r--r--sys/fs/msdosfs/msdosfs_vnops.c37
2 files changed, 54 insertions, 36 deletions
diff --git a/sys/fs/msdosfs/msdosfs_vfsops.c b/sys/fs/msdosfs/msdosfs_vfsops.c
index 5bc7ba8..d1999e9 100644
--- a/sys/fs/msdosfs/msdosfs_vfsops.c
+++ b/sys/fs/msdosfs/msdosfs_vfsops.c
@@ -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
};
@@ -467,6 +467,21 @@ mountmsdosfs(devvp, mp, td)
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
* the fields that are different between dos 5 and dos 3.3.
@@ -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);
diff --git a/sys/fs/msdosfs/msdosfs_vnops.c b/sys/fs/msdosfs/msdosfs_vnops.c
index 57b0ec8..cc0a046 100644
--- a/sys/fs/msdosfs/msdosfs_vnops.c
+++ b/sys/fs/msdosfs/msdosfs_vnops.c
@@ -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,
OpenPOWER on IntegriCloud