Rework the routines to convert a 5.x+ statfs structure (with fixed-size
64-bit counters) to a 4.x statfs structure (with long-sized counters). - For block counters, we scale up the block size sufficiently large so that the resulting block counts fit into a the long-sized (long for the ABI, so 32-bit in freebsd32) counters. In 4.x the NFS client's statfs VOP did this already. This can lie about the block size to 4.x binaries, but it presents a more accurate picture of the ratios of free and available space. - For non-block counters, fix the freebsd32 stats converter to cap the values at INT32_MAX rather than losing the upper 32-bits to match the behavior of the 4.x statfs conversion routine in vfs_syscalls.c Approved by: re (kensmith)
This commit is contained in:
parent
0e6ed4feab
commit
cc479dda4a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=172003
@ -135,28 +135,28 @@ freebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
|
||||
static void
|
||||
copy_statfs(struct statfs *in, struct statfs32 *out)
|
||||
{
|
||||
|
||||
|
||||
statfs_scale_blocks(in, INT32_MAX);
|
||||
bzero(out, sizeof(*out));
|
||||
CP(*in, *out, f_bsize);
|
||||
CP(*in, *out, f_iosize);
|
||||
out->f_iosize = MIN(in->f_iosize, INT32_MAX);
|
||||
CP(*in, *out, f_blocks);
|
||||
CP(*in, *out, f_bfree);
|
||||
CP(*in, *out, f_bavail);
|
||||
CP(*in, *out, f_files);
|
||||
CP(*in, *out, f_ffree);
|
||||
out->f_files = MIN(in->f_files, INT32_MAX);
|
||||
out->f_ffree = MIN(in->f_ffree, INT32_MAX);
|
||||
CP(*in, *out, f_fsid);
|
||||
CP(*in, *out, f_owner);
|
||||
CP(*in, *out, f_type);
|
||||
CP(*in, *out, f_flags);
|
||||
CP(*in, *out, f_flags);
|
||||
CP(*in, *out, f_syncwrites);
|
||||
CP(*in, *out, f_asyncwrites);
|
||||
out->f_syncwrites = MIN(in->f_syncwrites, INT32_MAX);
|
||||
out->f_asyncwrites = MIN(in->f_asyncwrites, INT32_MAX);
|
||||
strlcpy(out->f_fstypename,
|
||||
in->f_fstypename, MFSNAMELEN);
|
||||
strlcpy(out->f_mntonname,
|
||||
in->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN));
|
||||
CP(*in, *out, f_syncreads);
|
||||
CP(*in, *out, f_asyncreads);
|
||||
out->f_syncreads = MIN(in->f_syncreads, INT32_MAX);
|
||||
out->f_asyncreads = MIN(in->f_asyncreads, INT32_MAX);
|
||||
strlcpy(out->f_mntfromname,
|
||||
in->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN));
|
||||
}
|
||||
|
@ -205,6 +205,47 @@ quotactl(td, uap)
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Used by statfs conversion routines to scale the block size up if
|
||||
* necessary so that all of the block counts are <= 'max_size'. Note
|
||||
* that 'max_size' should be a bitmask, i.e. 2^n - 1 for some non-zero
|
||||
* value of 'n'.
|
||||
*/
|
||||
void
|
||||
statfs_scale_blocks(struct statfs *sf, long max_size)
|
||||
{
|
||||
uint64_t count;
|
||||
int shift;
|
||||
|
||||
KASSERT(powerof2(max_size + 1), ("%s: invalid max_size", __func__));
|
||||
|
||||
/*
|
||||
* Attempt to scale the block counts to give a more accurate
|
||||
* overview to userland of the ratio of free space to used
|
||||
* space. To do this, find the largest block count and compute
|
||||
* a divisor that lets it fit into a signed integer <= max_size.
|
||||
*/
|
||||
if (sf->f_bavail < 0)
|
||||
count = -sf->f_bavail;
|
||||
else
|
||||
count = sf->f_bavail;
|
||||
count = MAX(sf->f_blocks, MAX(sf->f_bfree, count));
|
||||
if (count <= max_size)
|
||||
return;
|
||||
|
||||
count >>= flsl(max_size);
|
||||
shift = 0;
|
||||
while (count > 0) {
|
||||
shift++;
|
||||
count >>=1;
|
||||
}
|
||||
|
||||
sf->f_bsize <<= shift;
|
||||
sf->f_blocks >>= shift;
|
||||
sf->f_bfree >>= shift;
|
||||
sf->f_bavail >>= shift;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get filesystem statistics.
|
||||
*/
|
||||
@ -636,12 +677,13 @@ cvtstatfs(nsp, osp)
|
||||
struct ostatfs *osp;
|
||||
{
|
||||
|
||||
statfs_scale_blocks(nsp, LONG_MAX);
|
||||
bzero(osp, sizeof(*osp));
|
||||
osp->f_bsize = MIN(nsp->f_bsize, LONG_MAX);
|
||||
osp->f_bsize = nsp->f_bsize;
|
||||
osp->f_iosize = MIN(nsp->f_iosize, LONG_MAX);
|
||||
osp->f_blocks = MIN(nsp->f_blocks, LONG_MAX);
|
||||
osp->f_bfree = MIN(nsp->f_bfree, LONG_MAX);
|
||||
osp->f_bavail = MIN(nsp->f_bavail, LONG_MAX);
|
||||
osp->f_blocks = nsp->f_blocks;
|
||||
osp->f_bfree = nsp->f_bfree;
|
||||
osp->f_bavail = nsp->f_bavail;
|
||||
osp->f_files = MIN(nsp->f_files, LONG_MAX);
|
||||
osp->f_ffree = MIN(nsp->f_ffree, LONG_MAX);
|
||||
osp->f_owner = nsp->f_owner;
|
||||
|
@ -653,6 +653,7 @@ struct mntarg *mount_arg(struct mntarg *ma, const char *name, const void *val, i
|
||||
struct mntarg *mount_argb(struct mntarg *ma, int flag, const char *name);
|
||||
struct mntarg *mount_argf(struct mntarg *ma, const char *name, const char *fmt, ...);
|
||||
struct mntarg *mount_argsu(struct mntarg *ma, const char *name, const void *val, int len);
|
||||
void statfs_scale_blocks(struct statfs *sf, long max_size);
|
||||
struct vfsconf *vfs_byname(const char *);
|
||||
struct vfsconf *vfs_byname_kld(const char *, struct thread *td, int *);
|
||||
void vfs_mount_destroy(struct mount *);
|
||||
|
Loading…
Reference in New Issue
Block a user