Page MenuHomeFreeBSD

D38987.diff
No OneTemporary

D38987.diff

diff --git a/bin/df/df.1 b/bin/df/df.1
--- a/bin/df/df.1
+++ b/bin/df/df.1
@@ -29,7 +29,7 @@
.\" @(#)df.1 8.3 (Berkeley) 5/8/95
.\" $FreeBSD$
.\"
-.Dd March 11, 2022
+.Dd March 29, 2023
.Dt DF 1
.Os
.Sh NAME
@@ -246,6 +246,17 @@
Filesystem Size Used Avail Capacity Mounted on
/dev/ada1p2 213G 152G 44G 78% /
.Ed
+.Sh NOTES
+For non-Unix file systems, the reported values of used and free inodes
+may have a different meaning than that of used and available files and
+directories.
+An example is msdosfs, which in the case of FAT12 or FAT16 file systems
+reports the number of available and free root directory entries instead
+of inodes
+.Po
+where 1 to 21 such directory entries are required to store
+each file or directory name or disk label
+.Pc .
.Sh SEE ALSO
.Xr lsvfs 1 ,
.Xr quota 1 ,
diff --git a/lib/libc/sys/statfs.2 b/lib/libc/sys/statfs.2
--- a/lib/libc/sys/statfs.2
+++ b/lib/libc/sys/statfs.2
@@ -28,7 +28,7 @@
.\" @(#)statfs.2 8.5 (Berkeley) 5/24/95
.\" $FreeBSD$
.\"
-.Dd March 30, 2020
+.Dd March 29, 2023
.Dt STATFS 2
.Os
.Sh NAME
@@ -230,6 +230,22 @@
.It Bq Er EINTEGRITY
Corrupted data was detected while reading from the file system.
.El
+.Sh NOTES
+The fields in the
+.Vt statfs
+structure have been defined to provide the parameters relevant for
+traditional
+.Tm UNIX
+file systems.
+For some other file systems, values that have similar, but not
+identical, semantics to those described above may be returned.
+An example is msdosfs, which in case of FAT12 or FAT13 file systems
+reports the number of available and of free root directory entries
+instead of inodes
+.Po
+where 1 to 21 such directory entries are required to store
+each file or directory name or disk label
+.Pc .
.Sh SEE ALSO
.Xr fhstatfs 2 ,
.Xr getfsstat 2
diff --git a/sys/fs/msdosfs/msdosfs_lookup.c b/sys/fs/msdosfs/msdosfs_lookup.c
--- a/sys/fs/msdosfs/msdosfs_lookup.c
+++ b/sys/fs/msdosfs/msdosfs_lookup.c
@@ -684,6 +684,7 @@
return error;
}
ndep = bptoep(pmp, bp, ddep->de_fndoffset);
+ rootde_alloced(ddep);
DE_EXTERNALIZE(ndep, dep);
@@ -721,6 +722,7 @@
ndep--;
ddep->de_fndoffset -= sizeof(struct direntry);
}
+ rootde_alloced(ddep);
if (!unix2winfn(un, unlen, (struct winentry *)ndep,
cnt++, chksum, pmp))
break;
@@ -1015,6 +1017,7 @@
*/
offset -= sizeof(struct direntry);
ep--->deName[0] = SLOT_DELETED;
+ rootde_freed(pdep);
if ((pmp->pm_flags & MSDOSFSMNT_NOWIN95)
|| !(offset & pmp->pm_crbomask)
|| ep->deAttributes != ATTR_WIN95)
diff --git a/sys/fs/msdosfs/msdosfs_vfsops.c b/sys/fs/msdosfs/msdosfs_vfsops.c
--- a/sys/fs/msdosfs/msdosfs_vfsops.c
+++ b/sys/fs/msdosfs/msdosfs_vfsops.c
@@ -409,6 +409,97 @@
return (0);
}
+/*
+ * The FAT12 and FAT16 file systems use a limited size root directory that
+ * can be created with 1 to 65535 entries for files, directories, or a disk
+ * label (but DOS or Windows creates at most 512 root directory entries).
+ * This function calculates the number of free root directory entries by
+ * counting the non-deleted entries (not starting with 0xE5) and by adding
+ * the amount of never used entries (with the position indicated by an
+ * entry that starts with 0x00).
+ */
+static int
+rootdir_free(struct msdosfsmount* pmp)
+{
+ struct buf *bp;
+ struct direntry *dep;
+ u_long readsize;
+ int dirclu;
+ int diridx;
+ int dirmax;
+ int dirleft;
+ int ffree;
+
+ dirclu = pmp->pm_rootdirblk;
+
+ /*
+ * The msdosfs code ignores pm_RootDirEnts and uses pm_rootdirsize
+ * (measured in DEV_BSIZE) to prevent excess root dir allocations.
+ */
+ dirleft = howmany(pmp->pm_rootdirsize * DEV_BSIZE,
+ sizeof(struct direntry));
+
+ /* Read in chunks of default maximum root directory size */
+ readsize = 512 * sizeof(struct direntry);
+
+#ifdef MSDOSFS_DEBUG
+ printf("rootdir_free: blkpersec=%lu fatblksize=%lu dirsize=%lu "
+ "firstclu=%lu dirclu=%d entries=%d rootdirsize=%lu "
+ "bytespersector=%hu bytepercluster=%lu\n",
+ pmp->pm_BlkPerSec, pmp->pm_fatblocksize, readsize,
+ pmp->pm_firstcluster, dirclu, dirleft, pmp->pm_rootdirsize,
+ pmp->pm_BytesPerSec, pmp->pm_bpcluster);
+#endif
+ ffree = dirleft;
+ while (dirleft > 0 && ffree > 0) {
+ if (readsize > dirleft * sizeof(struct direntry))
+ readsize = dirleft * sizeof(struct direntry);
+#ifdef MSDOSFS_DEBUG
+ printf("rootdir_free: dirclu=%d dirleft=%d readsize=%lu\n",
+ dirclu, dirleft, readsize);
+#endif
+ if (bread(pmp->pm_devvp, dirclu, readsize, NOCRED, &bp) != 0) {
+ printf("rootdir_free: read error\n");
+ if (bp != NULL)
+ brelse(bp);
+ return (-1);
+ }
+ dirmax = readsize / sizeof(struct direntry);
+ for (diridx = 0; diridx < dirmax && dirleft > 0;
+ diridx++, dirleft--) {
+ dep = (struct direntry*)bp->b_data + diridx;
+#ifdef MSDOSFS_DEBUG
+ if (dep->deName[0] == SLOT_DELETED)
+ printf("rootdir_free: idx=%d <deleted>\n",
+ diridx);
+ else if (dep->deName[0] == SLOT_EMPTY)
+ printf("rootdir_free: idx=%d <end marker>\n",
+ diridx);
+ else if (dep->deAttributes == ATTR_WIN95)
+ printf("rootdir_free: idx=%d <LFN part %d>\n",
+ diridx, (dep->deName[0] & 0x1f) + 1);
+ else if (dep->deAttributes & ATTR_VOLUME)
+ printf("rootdir_free: idx=%d label='%11.11s'\n",
+ diridx, dep->deName);
+ else if (dep->deAttributes & ATTR_DIRECTORY)
+ printf("rootdir_free: idx=%d dir='%11.11s'\n",
+ diridx, dep->deName);
+ else
+ printf("rootdir_free: idx=%d file='%11.11s'\n",
+ diridx, dep->deName);
+#endif
+ if (dep->deName[0] == SLOT_EMPTY)
+ dirleft = 0;
+ else if (dep->deName[0] != SLOT_DELETED)
+ ffree--;
+ }
+ brelse(bp);
+ bp = NULL;
+ dirclu += readsize / DEV_BSIZE;
+ }
+ return (ffree);
+}
+
static int
mountmsdosfs(struct vnode *odevvp, struct mount *mp)
{
@@ -747,6 +838,15 @@
goto error_exit;
pmp->pm_fmod = 1;
}
+
+ if (FAT32(pmp)) {
+ pmp->pm_rootdirfree = 0;
+ } else {
+ pmp->pm_rootdirfree = rootdir_free(pmp);
+ if (pmp->pm_rootdirfree < 0)
+ goto error_exit;
+ }
+
mp->mnt_data = pmp;
mp->mnt_stat.f_fsid.val[0] = dev2udev(dev);
mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
@@ -948,8 +1048,9 @@
sbp->f_blocks = pmp->pm_maxcluster + 1;
sbp->f_bfree = pmp->pm_freeclustercount;
sbp->f_bavail = pmp->pm_freeclustercount;
- sbp->f_files = pmp->pm_RootDirEnts; /* XXX */
- sbp->f_ffree = 0; /* what to put in here? */
+ sbp->f_files = howmany(pmp->pm_rootdirsize * DEV_BSIZE,
+ sizeof(struct direntry));
+ sbp->f_ffree = pmp->pm_rootdirfree;
return (0);
}
diff --git a/sys/fs/msdosfs/msdosfsmount.h b/sys/fs/msdosfs/msdosfsmount.h
--- a/sys/fs/msdosfs/msdosfsmount.h
+++ b/sys/fs/msdosfs/msdosfsmount.h
@@ -108,6 +108,7 @@
u_int pm_fatmult; /* these 2 values are used in FAT */
u_int pm_fatdiv; /* offset computation */
u_int pm_curfat; /* current FAT for FAT32 (0 otherwise) */
+ int pm_rootdirfree; /* number of free slots in FAT12/16 root directory */
u_int *pm_inusemap; /* ptr to bitmap of in-use clusters */
uint64_t pm_flags; /* see below */
void *pm_u2w; /* Local->Unicode iconv handle */
@@ -222,6 +223,22 @@
? roottobn((pmp), (dirofs)) \
: cntobn((pmp), (dirclu)))
+/*
+ * Increment the number of used entries in a fixed size FAT12/16 root
+ * directory
+ */
+#define rootde_alloced(dep) \
+ if ((dep)->de_StartCluster == MSDOSFSROOT) \
+ (dep)->de_pmp->pm_rootdirfree--;
+
+/*
+ * Decrement the number of used entries in a fixed size FAT12/16 root
+ * directory
+ */
+#define rootde_freed(dep) \
+ if ((dep)->de_StartCluster == MSDOSFSROOT) \
+ (dep)->de_pmp->pm_rootdirfree++;
+
#define MSDOSFS_LOCK_MP(pmp) \
lockmgr(&(pmp)->pm_fatlock, LK_EXCLUSIVE, NULL)
#define MSDOSFS_UNLOCK_MP(pmp) \

File Metadata

Mime Type
text/plain
Expires
Mon, Sep 30, 2:25 PM (21 h, 56 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
13188055
Default Alt Text
D38987.diff (7 KB)

Event Timeline