summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bin/df/df.c48
-rw-r--r--sys/kern/syscalls.master18
-rw-r--r--sys/kern/vfs_bio.c4
-rw-r--r--sys/kern/vfs_cluster.c4
-rw-r--r--sys/kern/vfs_extattr.c309
-rw-r--r--sys/kern/vfs_syscalls.c309
-rw-r--r--sys/sys/mount.h41
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c11
8 files changed, 676 insertions, 68 deletions
diff --git a/bin/df/df.c b/bin/df/df.c
index 97d6f94..83c7d2d 100644
--- a/bin/df/df.c
+++ b/bin/df/df.c
@@ -120,9 +120,9 @@ typedef enum { NONE, KILO, MEGA, GIGA, TERA, PETA, UNIT_MAX } unit_t;
static unit_t unitp [] = { NONE, KILO, MEGA, GIGA, TERA, PETA };
static char *getmntpt(const char *);
-static size_t longwidth(long);
+static size_t int64width(int64_t);
static char *makenetvfslist(void);
-static void prthuman(const struct statfs *, size_t);
+static void prthuman(const struct statfs *, int64_t);
static void prthumanval(double);
static void prtstat(struct statfs *, struct maxwidths *);
static size_t regetmntinfo(struct statfs **, long, const char **);
@@ -371,7 +371,7 @@ unit_adjust(double *val)
}
static void
-prthuman(const struct statfs *sfsp, size_t used)
+prthuman(const struct statfs *sfsp, int64_t used)
{
prthumanval((double)sfsp->f_blocks * (double)sfsp->f_bsize);
@@ -408,10 +408,10 @@ prthumanval(double bytes)
static void
prtstat(struct statfs *sfsp, struct maxwidths *mwp)
{
- static long blocksize;
+ static u_long blocksize;
static int headerlen, timesthrough = 0;
static const char *header;
- size_t used, availblks, inodes;
+ int64_t used, availblks, inodes;
if (++timesthrough == 1) {
mwp->mntfrom = max(mwp->mntfrom, strlen("Filesystem"));
@@ -445,21 +445,23 @@ prtstat(struct statfs *sfsp, struct maxwidths *mwp)
if (hflag) {
prthuman(sfsp, used);
} else {
- (void)printf(" %*ld %*ld %*ld",
- (u_int)mwp->total, fsbtoblk(sfsp->f_blocks, sfsp->f_bsize, blocksize),
- (u_int)mwp->used, fsbtoblk(used, sfsp->f_bsize, blocksize),
- (u_int)mwp->avail, fsbtoblk(sfsp->f_bavail, sfsp->f_bsize,
- blocksize));
+ (void)printf(" %*qd %*qd %*qd",
+ (u_int)mwp->total,
+ (intmax_t)fsbtoblk(sfsp->f_blocks, sfsp->f_bsize, blocksize),
+ (u_int)mwp->used,
+ (intmax_t)fsbtoblk(used, sfsp->f_bsize, blocksize),
+ (u_int)mwp->avail,
+ (intmax_t)fsbtoblk(sfsp->f_bavail, sfsp->f_bsize, blocksize));
}
(void)printf(" %5.0f%%",
availblks == 0 ? 100.0 : (double)used / (double)availblks * 100.0);
if (iflag) {
inodes = sfsp->f_files;
used = inodes - sfsp->f_ffree;
- (void)printf(" %*lu %*lu %4.0f%% ",
- (u_int)mwp->iused, (u_long)used,
- (u_int)mwp->ifree, sfsp->f_ffree,
- inodes == 0 ? 100.0 : (double)used / (double)inodes * 100.0);
+ (void)printf(" %*qd %*qd %4.0f%% ",
+ (u_int)mwp->iused, (intmax_t)used,
+ (u_int)mwp->ifree, (intmax_t)sfsp->f_ffree,
+ inodes == 0 ? 100.0 : (double)used / (double)inodes * 100.0);
} else
(void)printf(" ");
(void)printf(" %s\n", sfsp->f_mntonname);
@@ -472,27 +474,27 @@ prtstat(struct statfs *sfsp, struct maxwidths *mwp)
static void
update_maxwidths(struct maxwidths *mwp, const struct statfs *sfsp)
{
- static long blocksize = 0;
+ static u_long blocksize = 0;
int dummy;
if (blocksize == 0)
getbsize(&dummy, &blocksize);
mwp->mntfrom = max(mwp->mntfrom, strlen(sfsp->f_mntfromname));
- mwp->total = max(mwp->total, longwidth(fsbtoblk(sfsp->f_blocks,
+ mwp->total = max(mwp->total, int64width(
+ fsbtoblk((int64_t)sfsp->f_blocks, sfsp->f_bsize, blocksize)));
+ mwp->used = max(mwp->used, int64width(fsbtoblk((int64_t)sfsp->f_blocks -
+ (int64_t)sfsp->f_bfree, sfsp->f_bsize, blocksize)));
+ mwp->avail = max(mwp->avail, int64width(fsbtoblk(sfsp->f_bavail,
sfsp->f_bsize, blocksize)));
- mwp->used = max(mwp->used, longwidth(fsbtoblk(sfsp->f_blocks -
- sfsp->f_bfree, sfsp->f_bsize, blocksize)));
- mwp->avail = max(mwp->avail, longwidth(fsbtoblk(sfsp->f_bavail,
- sfsp->f_bsize, blocksize)));
- mwp->iused = max(mwp->iused, longwidth(sfsp->f_files -
+ mwp->iused = max(mwp->iused, int64width((int64_t)sfsp->f_files -
sfsp->f_ffree));
- mwp->ifree = max(mwp->ifree, longwidth(sfsp->f_ffree));
+ mwp->ifree = max(mwp->ifree, int64width(sfsp->f_ffree));
}
/* Return the width in characters of the specified long. */
static size_t
-longwidth(long val)
+int64width(int64_t val)
{
size_t len;
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
index 5303969..dab5d43 100644
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -68,7 +68,7 @@
15 STD POSIX { int chmod(char *path, int mode); }
16 STD POSIX { int chown(char *path, int uid, int gid); }
17 MSTD BSD { int obreak(char *nsize); } break obreak_args int
-18 STD BSD { int getfsstat(struct statfs *buf, long bufsize, \
+18 COMPAT4 BSD { int getfsstat(struct ostatfs *buf, long bufsize, \
int flags); }
19 COMPAT POSIX { long lseek(int fd, long offset, int whence); }
20 MSTD POSIX { pid_t getpid(void); }
@@ -252,8 +252,8 @@
155 MNOIMPL BSD { int nfssvc(int flag, caddr_t argp); }
156 COMPAT BSD { int getdirentries(int fd, char *buf, u_int count, \
long *basep); }
-157 STD BSD { int statfs(char *path, struct statfs *buf); }
-158 STD BSD { int fstatfs(int fd, struct statfs *buf); }
+157 COMPAT4 BSD { int statfs(char *path, struct ostatfs *buf); }
+158 COMPAT4 BSD { int fstatfs(int fd, struct ostatfs *buf); }
159 UNIMPL NOHIDE nosys
160 UNIMPL NOHIDE nosys
161 STD BSD { int getfh(char *fname, struct fhandle *fhp); }
@@ -439,7 +439,7 @@
295 UNIMPL NOHIDE nosys
296 UNIMPL NOHIDE nosys
; XXX 297 is 300 in NetBSD
-297 STD BSD { int fhstatfs(const struct fhandle *u_fhp, struct statfs *buf); }
+297 COMPAT4 BSD { int fhstatfs(const struct fhandle *u_fhp, struct ostatfs *buf); }
298 STD BSD { int fhopen(const struct fhandle *u_fhp, int flags); }
299 STD BSD { int fhstat(const struct fhandle *u_fhp, struct stat *sb); }
; syscall numbers for FreeBSD
@@ -574,10 +574,12 @@
struct sf_hdtr *hdtr, off_t *sbytes, int flags); }
394 MSTD BSD { int mac_syscall(const char *policy, int call, \
void *arg); }
-395 UNIMPL NOHIDE nosys
-396 UNIMPL NOHIDE nosys
-397 UNIMPL NOHIDE nosys
-398 UNIMPL NOHIDE nosys
+395 STD BSD { int getfsstat(struct statfs *buf, long bufsize, \
+ int flags); }
+396 STD BSD { int statfs(char *path, struct statfs *buf); }
+397 STD BSD { int fstatfs(int fd, struct statfs *buf); }
+398 STD BSD { int fhstatfs(const struct fhandle *u_fhp, \
+ struct statfs *buf); }
399 UNIMPL NOHIDE nosys
400 MNOSTD BSD { int ksem_close(semid_t id); }
401 MNOSTD BSD { int ksem_post(semid_t id); }
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index c75362d..595d39c 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -3236,8 +3236,8 @@ bufdone(struct buf *bp)
(int) m->pindex, (int)(foff >> 32),
(int) foff & 0xffffffff, resid, i);
if (!vn_isdisk(vp, NULL))
- printf(" iosize: %ld, lblkno: %jd, flags: 0x%x, npages: %d\n",
- bp->b_vp->v_mount->mnt_stat.f_iosize,
+ printf(" iosize: %jd, lblkno: %jd, flags: 0x%x, npages: %d\n",
+ (intmax_t)bp->b_vp->v_mount->mnt_stat.f_iosize,
(intmax_t) bp->b_lblkno,
bp->b_flags, bp->b_npages);
else
diff --git a/sys/kern/vfs_cluster.c b/sys/kern/vfs_cluster.c
index dc86fb9..3fa110b 100644
--- a/sys/kern/vfs_cluster.c
+++ b/sys/kern/vfs_cluster.c
@@ -327,8 +327,8 @@ cluster_rbuild(vp, filesize, lbn, blkno, size, run, fbp)
GIANT_REQUIRED;
KASSERT(size == vp->v_mount->mnt_stat.f_iosize,
- ("cluster_rbuild: size %ld != filesize %ld\n",
- size, vp->v_mount->mnt_stat.f_iosize));
+ ("cluster_rbuild: size %ld != filesize %jd\n",
+ size, (intmax_t)vp->v_mount->mnt_stat.f_iosize));
/*
* avoid a division
diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c
index 3783010..a8900dc 100644
--- a/sys/kern/vfs_extattr.c
+++ b/sys/kern/vfs_extattr.c
@@ -226,11 +226,10 @@ statfs(td, uap)
struct statfs *buf;
} */ *uap;
{
- register struct mount *mp;
- register struct statfs *sp;
+ struct mount *mp;
+ struct statfs *sp, sb;
int error;
struct nameidata nd;
- struct statfs sb;
NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
if ((error = namei(&nd)) != 0)
@@ -244,10 +243,15 @@ statfs(td, uap)
if (error)
return (error);
#endif
+ /*
+ * Set these in case the underlying filesystem fails to do so.
+ */
+ sp->f_version = STATFS_VERSION;
+ sp->f_namemax = NAME_MAX;
+ sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
error = VFS_STATFS(mp, sp, td);
if (error)
return (error);
- sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
if (suser(td)) {
bcopy(sp, &sb, sizeof(sb));
sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
@@ -276,9 +280,8 @@ fstatfs(td, uap)
{
struct file *fp;
struct mount *mp;
- register struct statfs *sp;
+ struct statfs *sp, sb;
int error;
- struct statfs sb;
if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
return (error);
@@ -292,10 +295,15 @@ fstatfs(td, uap)
return (error);
#endif
sp = &mp->mnt_stat;
+ /*
+ * Set these in case the underlying filesystem fails to do so.
+ */
+ sp->f_version = STATFS_VERSION;
+ sp->f_namemax = NAME_MAX;
+ sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
error = VFS_STATFS(mp, sp, td);
if (error)
return (error);
- sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
if (suser(td)) {
bcopy(sp, &sb, sizeof(sb));
sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
@@ -323,8 +331,8 @@ getfsstat(td, uap)
int flags;
} */ *uap;
{
- register struct mount *mp, *nmp;
- register struct statfs *sp;
+ struct mount *mp, *nmp;
+ struct statfs *sp, sb;
caddr_t sfsp;
long count, maxcount, error;
@@ -346,6 +354,13 @@ getfsstat(td, uap)
if (sfsp && count < maxcount) {
sp = &mp->mnt_stat;
/*
+ * Set these in case the underlying filesystem
+ * fails to do so.
+ */
+ sp->f_version = STATFS_VERSION;
+ sp->f_namemax = NAME_MAX;
+ sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
+ /*
* If MNT_NOWAIT or MNT_LAZY is specified, do not
* refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY
* overrides MNT_WAIT.
@@ -358,7 +373,11 @@ getfsstat(td, uap)
vfs_unbusy(mp, td);
continue;
}
- sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
+ if (suser(td)) {
+ bcopy(sp, &sb, sizeof(sb));
+ sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
+ sp = &sb;
+ }
error = copyout(sp, sfsp, sizeof(*sp));
if (error) {
vfs_unbusy(mp, td);
@@ -379,6 +398,266 @@ getfsstat(td, uap)
return (0);
}
+#ifdef COMPAT_FREEBSD4
+/*
+ * Get old format filesystem statistics.
+ */
+static void cvtstatfs(struct thread *, struct statfs *, struct ostatfs *);
+
+#ifndef _SYS_SYSPROTO_H_
+struct freebsd4_statfs_args {
+ char *path;
+ struct ostatfs *buf;
+};
+#endif
+/* ARGSUSED */
+int
+freebsd4_statfs(td, uap)
+ struct thread *td;
+ struct freebsd4_statfs_args /* {
+ char *path;
+ struct ostatfs *buf;
+ } */ *uap;
+{
+ struct mount *mp;
+ struct statfs *sp;
+ struct ostatfs osb;
+ int error;
+ struct nameidata nd;
+
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
+ if ((error = namei(&nd)) != 0)
+ return (error);
+ mp = nd.ni_vp->v_mount;
+ sp = &mp->mnt_stat;
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+ vrele(nd.ni_vp);
+#ifdef MAC
+ error = mac_check_mount_stat(td->td_ucred, mp);
+ if (error)
+ return (error);
+#endif
+ error = VFS_STATFS(mp, sp, td);
+ if (error)
+ return (error);
+ sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
+ cvtstatfs(td, sp, &osb);
+ return (copyout(&osb, uap->buf, sizeof(osb)));
+}
+
+/*
+ * Get filesystem statistics.
+ */
+#ifndef _SYS_SYSPROTO_H_
+struct freebsd4_fstatfs_args {
+ int fd;
+ struct ostatfs *buf;
+};
+#endif
+/* ARGSUSED */
+int
+freebsd4_fstatfs(td, uap)
+ struct thread *td;
+ struct freebsd4_fstatfs_args /* {
+ int fd;
+ struct ostatfs *buf;
+ } */ *uap;
+{
+ struct file *fp;
+ struct mount *mp;
+ struct statfs *sp;
+ struct ostatfs osb;
+ int error;
+
+ if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
+ return (error);
+ mp = fp->f_vnode->v_mount;
+ fdrop(fp, td);
+ if (mp == NULL)
+ return (EBADF);
+#ifdef MAC
+ error = mac_check_mount_stat(td->td_ucred, mp);
+ if (error)
+ return (error);
+#endif
+ sp = &mp->mnt_stat;
+ error = VFS_STATFS(mp, sp, td);
+ if (error)
+ return (error);
+ sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
+ cvtstatfs(td, sp, &osb);
+ return (copyout(&osb, uap->buf, sizeof(osb)));
+}
+
+/*
+ * Get statistics on all filesystems.
+ */
+#ifndef _SYS_SYSPROTO_H_
+struct freebsd4_getfsstat_args {
+ struct ostatfs *buf;
+ long bufsize;
+ int flags;
+};
+#endif
+int
+freebsd4_getfsstat(td, uap)
+ struct thread *td;
+ register struct freebsd4_getfsstat_args /* {
+ struct ostatfs *buf;
+ long bufsize;
+ int flags;
+ } */ *uap;
+{
+ struct mount *mp, *nmp;
+ struct statfs *sp;
+ struct ostatfs osb;
+ caddr_t sfsp;
+ long count, maxcount, error;
+
+ maxcount = uap->bufsize / sizeof(struct ostatfs);
+ sfsp = (caddr_t)uap->buf;
+ count = 0;
+ mtx_lock(&mountlist_mtx);
+ for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
+#ifdef MAC
+ if (mac_check_mount_stat(td->td_ucred, mp) != 0) {
+ nmp = TAILQ_NEXT(mp, mnt_list);
+ continue;
+ }
+#endif
+ if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) {
+ nmp = TAILQ_NEXT(mp, mnt_list);
+ continue;
+ }
+ if (sfsp && count < maxcount) {
+ sp = &mp->mnt_stat;
+ /*
+ * If MNT_NOWAIT or MNT_LAZY is specified, do not
+ * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY
+ * overrides MNT_WAIT.
+ */
+ if (((uap->flags & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
+ (uap->flags & MNT_WAIT)) &&
+ (error = VFS_STATFS(mp, sp, td))) {
+ mtx_lock(&mountlist_mtx);
+ nmp = TAILQ_NEXT(mp, mnt_list);
+ vfs_unbusy(mp, td);
+ continue;
+ }
+ sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
+ cvtstatfs(td, sp, &osb);
+ error = copyout(&osb, sfsp, sizeof(osb));
+ if (error) {
+ vfs_unbusy(mp, td);
+ return (error);
+ }
+ sfsp += sizeof(osb);
+ }
+ count++;
+ mtx_lock(&mountlist_mtx);
+ nmp = TAILQ_NEXT(mp, mnt_list);
+ vfs_unbusy(mp, td);
+ }
+ mtx_unlock(&mountlist_mtx);
+ if (sfsp && count > maxcount)
+ td->td_retval[0] = maxcount;
+ else
+ td->td_retval[0] = count;
+ return (0);
+}
+
+/*
+ * Implement fstatfs() for (NFS) file handles.
+ */
+#ifndef _SYS_SYSPROTO_H_
+struct freebsd4_fhstatfs_args {
+ struct fhandle *u_fhp;
+ struct ostatfs *buf;
+};
+#endif
+int
+freebsd4_fhstatfs(td, uap)
+ struct thread *td;
+ struct freebsd4_fhstatfs_args /* {
+ struct fhandle *u_fhp;
+ struct ostatfs *buf;
+ } */ *uap;
+{
+ struct statfs *sp;
+ struct mount *mp;
+ struct vnode *vp;
+ struct ostatfs osb;
+ fhandle_t fh;
+ int error;
+
+ /*
+ * Must be super user
+ */
+ error = suser(td);
+ if (error)
+ return (error);
+
+ if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
+ return (error);
+
+ if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
+ return (ESTALE);
+ if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
+ return (error);
+ mp = vp->v_mount;
+ sp = &mp->mnt_stat;
+ vput(vp);
+#ifdef MAC
+ error = mac_check_mount_stat(td->td_ucred, mp);
+ if (error)
+ return (error);
+#endif
+ if ((error = VFS_STATFS(mp, sp, td)) != 0)
+ return (error);
+ sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
+ cvtstatfs(td, sp, &osb);
+ return (copyout(&osb, uap->buf, sizeof(osb)));
+}
+
+/*
+ * Convert a new format statfs structure to an old format statfs structure.
+ */
+static void
+cvtstatfs(td, nsp, osp)
+ struct thread *td;
+ struct statfs *nsp;
+ struct ostatfs *osp;
+{
+
+ bzero(osp, sizeof(*osp));
+ osp->f_bsize = MIN(nsp->f_bsize, LONG_MAX);
+ 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_files = MIN(nsp->f_files, LONG_MAX);
+ osp->f_ffree = MIN(nsp->f_ffree, LONG_MAX);
+ osp->f_owner = nsp->f_owner;
+ osp->f_type = nsp->f_type;
+ osp->f_flags = nsp->f_flags;
+ osp->f_syncwrites = MIN(nsp->f_syncwrites, LONG_MAX);
+ osp->f_asyncwrites = MIN(nsp->f_asyncwrites, LONG_MAX);
+ osp->f_syncreads = MIN(nsp->f_syncreads, LONG_MAX);
+ osp->f_asyncreads = MIN(nsp->f_asyncreads, LONG_MAX);
+ bcopy(nsp->f_fstypename, osp->f_fstypename,
+ MIN(MFSNAMELEN, OMNAMELEN));
+ bcopy(nsp->f_mntonname, osp->f_mntonname,
+ MIN(MFSNAMELEN, OMNAMELEN));
+ bcopy(nsp->f_mntfromname, osp->f_mntfromname,
+ MIN(MFSNAMELEN, OMNAMELEN));
+ if (suser(td)) {
+ osp->f_fsid.val[0] = osp->f_fsid.val[1] = 0;
+ } else {
+ osp->f_fsid = nsp->f_fsid;
+ }
+}
+#endif /* COMPAT_FREEBSD4 */
+
/*
* Change current working directory to a given file descriptor.
*/
@@ -3788,10 +4067,9 @@ fhstatfs(td, uap)
struct statfs *buf;
} */ *uap;
{
- struct statfs *sp;
+ struct statfs *sp, sb;
struct mount *mp;
struct vnode *vp;
- struct statfs sb;
fhandle_t fh;
int error;
@@ -3817,9 +4095,14 @@ fhstatfs(td, uap)
if (error)
return (error);
#endif
+ /*
+ * Set these in case the underlying filesystem fails to do so.
+ */
+ sp->f_version = STATFS_VERSION;
+ sp->f_namemax = NAME_MAX;
+ sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
if ((error = VFS_STATFS(mp, sp, td)) != 0)
return (error);
- sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
if (suser(td)) {
bcopy(sp, &sb, sizeof(sb));
sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 3783010..a8900dc 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -226,11 +226,10 @@ statfs(td, uap)
struct statfs *buf;
} */ *uap;
{
- register struct mount *mp;
- register struct statfs *sp;
+ struct mount *mp;
+ struct statfs *sp, sb;
int error;
struct nameidata nd;
- struct statfs sb;
NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
if ((error = namei(&nd)) != 0)
@@ -244,10 +243,15 @@ statfs(td, uap)
if (error)
return (error);
#endif
+ /*
+ * Set these in case the underlying filesystem fails to do so.
+ */
+ sp->f_version = STATFS_VERSION;
+ sp->f_namemax = NAME_MAX;
+ sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
error = VFS_STATFS(mp, sp, td);
if (error)
return (error);
- sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
if (suser(td)) {
bcopy(sp, &sb, sizeof(sb));
sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
@@ -276,9 +280,8 @@ fstatfs(td, uap)
{
struct file *fp;
struct mount *mp;
- register struct statfs *sp;
+ struct statfs *sp, sb;
int error;
- struct statfs sb;
if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
return (error);
@@ -292,10 +295,15 @@ fstatfs(td, uap)
return (error);
#endif
sp = &mp->mnt_stat;
+ /*
+ * Set these in case the underlying filesystem fails to do so.
+ */
+ sp->f_version = STATFS_VERSION;
+ sp->f_namemax = NAME_MAX;
+ sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
error = VFS_STATFS(mp, sp, td);
if (error)
return (error);
- sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
if (suser(td)) {
bcopy(sp, &sb, sizeof(sb));
sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
@@ -323,8 +331,8 @@ getfsstat(td, uap)
int flags;
} */ *uap;
{
- register struct mount *mp, *nmp;
- register struct statfs *sp;
+ struct mount *mp, *nmp;
+ struct statfs *sp, sb;
caddr_t sfsp;
long count, maxcount, error;
@@ -346,6 +354,13 @@ getfsstat(td, uap)
if (sfsp && count < maxcount) {
sp = &mp->mnt_stat;
/*
+ * Set these in case the underlying filesystem
+ * fails to do so.
+ */
+ sp->f_version = STATFS_VERSION;
+ sp->f_namemax = NAME_MAX;
+ sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
+ /*
* If MNT_NOWAIT or MNT_LAZY is specified, do not
* refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY
* overrides MNT_WAIT.
@@ -358,7 +373,11 @@ getfsstat(td, uap)
vfs_unbusy(mp, td);
continue;
}
- sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
+ if (suser(td)) {
+ bcopy(sp, &sb, sizeof(sb));
+ sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
+ sp = &sb;
+ }
error = copyout(sp, sfsp, sizeof(*sp));
if (error) {
vfs_unbusy(mp, td);
@@ -379,6 +398,266 @@ getfsstat(td, uap)
return (0);
}
+#ifdef COMPAT_FREEBSD4
+/*
+ * Get old format filesystem statistics.
+ */
+static void cvtstatfs(struct thread *, struct statfs *, struct ostatfs *);
+
+#ifndef _SYS_SYSPROTO_H_
+struct freebsd4_statfs_args {
+ char *path;
+ struct ostatfs *buf;
+};
+#endif
+/* ARGSUSED */
+int
+freebsd4_statfs(td, uap)
+ struct thread *td;
+ struct freebsd4_statfs_args /* {
+ char *path;
+ struct ostatfs *buf;
+ } */ *uap;
+{
+ struct mount *mp;
+ struct statfs *sp;
+ struct ostatfs osb;
+ int error;
+ struct nameidata nd;
+
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
+ if ((error = namei(&nd)) != 0)
+ return (error);
+ mp = nd.ni_vp->v_mount;
+ sp = &mp->mnt_stat;
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+ vrele(nd.ni_vp);
+#ifdef MAC
+ error = mac_check_mount_stat(td->td_ucred, mp);
+ if (error)
+ return (error);
+#endif
+ error = VFS_STATFS(mp, sp, td);
+ if (error)
+ return (error);
+ sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
+ cvtstatfs(td, sp, &osb);
+ return (copyout(&osb, uap->buf, sizeof(osb)));
+}
+
+/*
+ * Get filesystem statistics.
+ */
+#ifndef _SYS_SYSPROTO_H_
+struct freebsd4_fstatfs_args {
+ int fd;
+ struct ostatfs *buf;
+};
+#endif
+/* ARGSUSED */
+int
+freebsd4_fstatfs(td, uap)
+ struct thread *td;
+ struct freebsd4_fstatfs_args /* {
+ int fd;
+ struct ostatfs *buf;
+ } */ *uap;
+{
+ struct file *fp;
+ struct mount *mp;
+ struct statfs *sp;
+ struct ostatfs osb;
+ int error;
+
+ if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
+ return (error);
+ mp = fp->f_vnode->v_mount;
+ fdrop(fp, td);
+ if (mp == NULL)
+ return (EBADF);
+#ifdef MAC
+ error = mac_check_mount_stat(td->td_ucred, mp);
+ if (error)
+ return (error);
+#endif
+ sp = &mp->mnt_stat;
+ error = VFS_STATFS(mp, sp, td);
+ if (error)
+ return (error);
+ sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
+ cvtstatfs(td, sp, &osb);
+ return (copyout(&osb, uap->buf, sizeof(osb)));
+}
+
+/*
+ * Get statistics on all filesystems.
+ */
+#ifndef _SYS_SYSPROTO_H_
+struct freebsd4_getfsstat_args {
+ struct ostatfs *buf;
+ long bufsize;
+ int flags;
+};
+#endif
+int
+freebsd4_getfsstat(td, uap)
+ struct thread *td;
+ register struct freebsd4_getfsstat_args /* {
+ struct ostatfs *buf;
+ long bufsize;
+ int flags;
+ } */ *uap;
+{
+ struct mount *mp, *nmp;
+ struct statfs *sp;
+ struct ostatfs osb;
+ caddr_t sfsp;
+ long count, maxcount, error;
+
+ maxcount = uap->bufsize / sizeof(struct ostatfs);
+ sfsp = (caddr_t)uap->buf;
+ count = 0;
+ mtx_lock(&mountlist_mtx);
+ for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
+#ifdef MAC
+ if (mac_check_mount_stat(td->td_ucred, mp) != 0) {
+ nmp = TAILQ_NEXT(mp, mnt_list);
+ continue;
+ }
+#endif
+ if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) {
+ nmp = TAILQ_NEXT(mp, mnt_list);
+ continue;
+ }
+ if (sfsp && count < maxcount) {
+ sp = &mp->mnt_stat;
+ /*
+ * If MNT_NOWAIT or MNT_LAZY is specified, do not
+ * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY
+ * overrides MNT_WAIT.
+ */
+ if (((uap->flags & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
+ (uap->flags & MNT_WAIT)) &&
+ (error = VFS_STATFS(mp, sp, td))) {
+ mtx_lock(&mountlist_mtx);
+ nmp = TAILQ_NEXT(mp, mnt_list);
+ vfs_unbusy(mp, td);
+ continue;
+ }
+ sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
+ cvtstatfs(td, sp, &osb);
+ error = copyout(&osb, sfsp, sizeof(osb));
+ if (error) {
+ vfs_unbusy(mp, td);
+ return (error);
+ }
+ sfsp += sizeof(osb);
+ }
+ count++;
+ mtx_lock(&mountlist_mtx);
+ nmp = TAILQ_NEXT(mp, mnt_list);
+ vfs_unbusy(mp, td);
+ }
+ mtx_unlock(&mountlist_mtx);
+ if (sfsp && count > maxcount)
+ td->td_retval[0] = maxcount;
+ else
+ td->td_retval[0] = count;
+ return (0);
+}
+
+/*
+ * Implement fstatfs() for (NFS) file handles.
+ */
+#ifndef _SYS_SYSPROTO_H_
+struct freebsd4_fhstatfs_args {
+ struct fhandle *u_fhp;
+ struct ostatfs *buf;
+};
+#endif
+int
+freebsd4_fhstatfs(td, uap)
+ struct thread *td;
+ struct freebsd4_fhstatfs_args /* {
+ struct fhandle *u_fhp;
+ struct ostatfs *buf;
+ } */ *uap;
+{
+ struct statfs *sp;
+ struct mount *mp;
+ struct vnode *vp;
+ struct ostatfs osb;
+ fhandle_t fh;
+ int error;
+
+ /*
+ * Must be super user
+ */
+ error = suser(td);
+ if (error)
+ return (error);
+
+ if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
+ return (error);
+
+ if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
+ return (ESTALE);
+ if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
+ return (error);
+ mp = vp->v_mount;
+ sp = &mp->mnt_stat;
+ vput(vp);
+#ifdef MAC
+ error = mac_check_mount_stat(td->td_ucred, mp);
+ if (error)
+ return (error);
+#endif
+ if ((error = VFS_STATFS(mp, sp, td)) != 0)
+ return (error);
+ sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
+ cvtstatfs(td, sp, &osb);
+ return (copyout(&osb, uap->buf, sizeof(osb)));
+}
+
+/*
+ * Convert a new format statfs structure to an old format statfs structure.
+ */
+static void
+cvtstatfs(td, nsp, osp)
+ struct thread *td;
+ struct statfs *nsp;
+ struct ostatfs *osp;
+{
+
+ bzero(osp, sizeof(*osp));
+ osp->f_bsize = MIN(nsp->f_bsize, LONG_MAX);
+ 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_files = MIN(nsp->f_files, LONG_MAX);
+ osp->f_ffree = MIN(nsp->f_ffree, LONG_MAX);
+ osp->f_owner = nsp->f_owner;
+ osp->f_type = nsp->f_type;
+ osp->f_flags = nsp->f_flags;
+ osp->f_syncwrites = MIN(nsp->f_syncwrites, LONG_MAX);
+ osp->f_asyncwrites = MIN(nsp->f_asyncwrites, LONG_MAX);
+ osp->f_syncreads = MIN(nsp->f_syncreads, LONG_MAX);
+ osp->f_asyncreads = MIN(nsp->f_asyncreads, LONG_MAX);
+ bcopy(nsp->f_fstypename, osp->f_fstypename,
+ MIN(MFSNAMELEN, OMNAMELEN));
+ bcopy(nsp->f_mntonname, osp->f_mntonname,
+ MIN(MFSNAMELEN, OMNAMELEN));
+ bcopy(nsp->f_mntfromname, osp->f_mntfromname,
+ MIN(MFSNAMELEN, OMNAMELEN));
+ if (suser(td)) {
+ osp->f_fsid.val[0] = osp->f_fsid.val[1] = 0;
+ } else {
+ osp->f_fsid = nsp->f_fsid;
+ }
+}
+#endif /* COMPAT_FREEBSD4 */
+
/*
* Change current working directory to a given file descriptor.
*/
@@ -3788,10 +4067,9 @@ fhstatfs(td, uap)
struct statfs *buf;
} */ *uap;
{
- struct statfs *sp;
+ struct statfs *sp, sb;
struct mount *mp;
struct vnode *vp;
- struct statfs sb;
fhandle_t fh;
int error;
@@ -3817,9 +4095,14 @@ fhstatfs(td, uap)
if (error)
return (error);
#endif
+ /*
+ * Set these in case the underlying filesystem fails to do so.
+ */
+ sp->f_version = STATFS_VERSION;
+ sp->f_namemax = NAME_MAX;
+ sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
if ((error = VFS_STATFS(mp, sp, td)) != 0)
return (error);
- sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
if (suser(td)) {
bcopy(sp, &sb, sizeof(sb));
sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
diff --git a/sys/sys/mount.h b/sys/sys/mount.h
index 61aeb84..5ebf578 100644
--- a/sys/sys/mount.h
+++ b/sys/sys/mount.h
@@ -62,13 +62,41 @@ struct fid {
/*
* filesystem statistics
*/
+#define MFSNAMELEN 16 /* length of type name including null */
+#define MNAMELEN 88 /* size of on/from name bufs */
+#define STATFS_VERSION 0x20030518 /* current version number */
+struct statfs {
+ uint32_t f_version; /* structure version number */
+ uint32_t f_type; /* type of filesystem */
+ uint64_t f_flags; /* copy of mount exported flags */
+ uint64_t f_bsize; /* filesystem fragment size */
+ uint64_t f_iosize; /* optimal transfer block size */
+ uint64_t f_blocks; /* total data blocks in filesystem */
+ uint64_t f_bfree; /* free blocks in filesystem */
+ int64_t f_bavail; /* free blocks avail to non-superuser */
+ uint64_t f_files; /* total file nodes in filesystem */
+ int64_t f_ffree; /* free nodes avail to non-superuser */
+ uint64_t f_syncwrites; /* count of sync writes since mount */
+ uint64_t f_asyncwrites; /* count of async writes since mount */
+ uint64_t f_syncreads; /* count of sync reads since mount */
+ uint64_t f_asyncreads; /* count of async reads since mount */
+ uint64_t f_spare[10]; /* unused spare */
+ uint32_t f_namemax; /* maximum filename length */
+ uid_t f_owner; /* user that mounted the filesystem */
+ fsid_t f_fsid; /* filesystem id */
+ char f_charspare[80]; /* spare string space */
+ char f_fstypename[MFSNAMELEN]; /* filesystem type name */
+ char f_mntfromname[MNAMELEN]; /* mounted filesystem */
+ char f_mntonname[MNAMELEN]; /* directory on which mounted */
+};
-#define MFSNAMELEN 16 /* length of fs type name, including null */
-#define MNAMELEN (88 - 2 * sizeof(long)) /* size of on/from name bufs */
+#ifdef _KERNEL
+#define OMFSNAMELEN 16 /* length of fs type name, including null */
+#define OMNAMELEN (88 - 2 * sizeof(long)) /* size of on/from name bufs */
/* XXX getfsstat.2 is out of date with write and read counter changes here. */
/* XXX statfs.2 is out of date with read counter changes here. */
-struct statfs {
+struct ostatfs {
long f_spare2; /* placeholder */
long f_bsize; /* fundamental filesystem block size */
long f_iosize; /* optimal transfer block size */
@@ -83,12 +111,12 @@ struct statfs {
int f_flags; /* copy of mount exported flags */
long f_syncwrites; /* count of sync writes since mount */
long f_asyncwrites; /* count of async writes since mount */
- char f_fstypename[MFSNAMELEN]; /* fs type name */
- char f_mntonname[MNAMELEN]; /* directory on which mounted */
+ char f_fstypename[OMFSNAMELEN]; /* fs type name */
+ char f_mntonname[OMNAMELEN]; /* directory on which mounted */
long f_syncreads; /* count of sync reads since mount */
long f_asyncreads; /* count of async reads since mount */
short f_spares1; /* unused spare */
- char f_mntfromname[MNAMELEN];/* mounted filesystem */
+ char f_mntfromname[OMNAMELEN];/* mounted filesystem */
short f_spares2; /* unused spare */
/*
* XXX on machines where longs are aligned to 8-byte boundaries, there
@@ -98,7 +126,6 @@ struct statfs {
long f_spare[2]; /* unused spare */
};
-#ifdef _KERNEL
#define MMAXOPTIONLEN 65536 /* maximum length of a mount option */
TAILQ_HEAD(vnodelst, vnode);
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index f78253e..e188ed4 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -1076,6 +1076,7 @@ ffs_statfs(mp, sbp, td)
fs = ump->um_fs;
if (fs->fs_magic != FS_UFS1_MAGIC && fs->fs_magic != FS_UFS2_MAGIC)
panic("ffs_statfs");
+ sbp->f_version = STATFS_VERSION;
sbp->f_bsize = fs->fs_fsize;
sbp->f_iosize = fs->fs_bsize;
sbp->f_blocks = fs->fs_dsize;
@@ -1085,8 +1086,18 @@ ffs_statfs(mp, sbp, td)
dbtofsb(fs, fs->fs_pendingblocks);
sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO;
sbp->f_ffree = fs->fs_cstotal.cs_nifree + fs->fs_pendinginodes;
+ sbp->f_namemax = NAME_MAX;
if (sbp != &mp->mnt_stat) {
+ sbp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
sbp->f_type = mp->mnt_vfc->vfc_typenum;
+ sbp->f_syncwrites = mp->mnt_stat.f_syncwrites;
+ sbp->f_asyncwrites = mp->mnt_stat.f_asyncwrites;
+ sbp->f_syncreads = mp->mnt_stat.f_syncreads;
+ sbp->f_asyncreads = mp->mnt_stat.f_asyncreads;
+ sbp->f_owner = mp->mnt_stat.f_owner;
+ sbp->f_fsid = mp->mnt_stat.f_fsid;
+ bcopy((caddr_t)mp->mnt_stat.f_fstypename,
+ (caddr_t)&sbp->f_fstypename[0], MFSNAMELEN);
bcopy((caddr_t)mp->mnt_stat.f_mntonname,
(caddr_t)&sbp->f_mntonname[0], MNAMELEN);
bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
OpenPOWER on IntegriCloud