summaryrefslogtreecommitdiff
path: root/sys/compat/freebsd/freebsd_file.c
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>1999-05-31 17:34:56 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>1999-05-31 17:34:56 +0000
commitbc8362e4ef1c185f7c1d9aec69d91f269c97d4e2 (patch)
tree9194d1773b772347d76766611948ee38e1002058 /sys/compat/freebsd/freebsd_file.c
parent7a1b6dcd69cb5defd76dca41d6f8252a3140fb91 (diff)
New struct statfs with mount options. NOTE: this replaces statfs(2),
fstatfs(2), and getfsstat(2) so you will need to build a new kernel before doing a "make build" or you will get "unimplemented syscall" errors. The new struct statfs has the following featuires: o Has a u_int32_t flags field--now softdep can have a real flag. o Uses u_int32_t instead of longs (nicer on the alpha). Note: the man page used to lie about setting invalid/unused fields to -1. SunOS does that but our code never has. o Gets rid of f_type completely. It hasn't been used since NetBSD 0.9 and having it there but always 0 is confusing. It is conceivable that this may cause some old code to not compile but that is better than silently breaking. o Adds a mount_info union that contains the FSTYPE_args struct. This means that "mount" can now tell you all the options a filesystem was mounted with. This is especially nice for NFS. Other changes: o The linux statfs emulation didn't convert between BSD fs names and linux f_type numbers. Now it does, since the BSD f_type number is useless to linux apps (and has been removed anyway) o FreeBSD's struct statfs is different from our (both old and new) and thus needs conversion. Previously, the OpenBSD syscalls were used without any real translation. o mount(8) will now show extra info when invoked with no arguments. However, to see *everything* you need to use the -v (verbose) flag.
Diffstat (limited to 'sys/compat/freebsd/freebsd_file.c')
-rw-r--r--sys/compat/freebsd/freebsd_file.c181
1 files changed, 177 insertions, 4 deletions
diff --git a/sys/compat/freebsd/freebsd_file.c b/sys/compat/freebsd/freebsd_file.c
index 52d8c6cfe99..79d9f4f4039 100644
--- a/sys/compat/freebsd/freebsd_file.c
+++ b/sys/compat/freebsd/freebsd_file.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: freebsd_file.c,v 1.6 1997/06/17 11:11:07 deraadt Exp $ */
+/* $OpenBSD: freebsd_file.c,v 1.7 1999/05/31 17:34:44 millert Exp $ */
/* $NetBSD: freebsd_file.c,v 1.3 1996/05/03 17:03:09 christos Exp $ */
/*
@@ -43,6 +43,7 @@
#include <sys/filedesc.h>
#include <sys/ioctl.h>
#include <sys/kernel.h>
+#include <sys/vnode.h>
#include <sys/mount.h>
#include <sys/malloc.h>
@@ -56,6 +57,27 @@
const char freebsd_emul_path[] = "/emul/freebsd";
static char * convert_from_freebsd_mount_type __P((int));
+void statfs_to_freebsd_statfs __P((struct proc *, struct mount *, struct statfs *, struct freebsd_statfs *));
+
+struct freebsd_statfs {
+ long f_spare2; /* placeholder */
+ long f_bsize; /* fundamental file system block size */
+ long f_iosize; /* optimal transfer block size */
+ long f_blocks; /* total data blocks in file system */
+ long f_bfree; /* free blocks in fs */
+ long f_bavail; /* free blocks avail to non-superuser */
+ long f_files; /* total file nodes in file system */
+ long f_ffree; /* free file nodes in fs */
+ fsid_t f_fsid; /* file system id */
+ uid_t f_owner; /* user that mounted the filesystem */
+ int f_type; /* type of filesystem */
+ 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_mntfromname[MNAMELEN];/* mounted filesystem */
+};
static char *
convert_from_freebsd_mount_type(type)
@@ -508,20 +530,171 @@ freebsd_sys_rmdir(p, v, retval)
return sys_rmdir(p, uap, retval);
}
+/*
+ * Convert struct statfs -> struct freebsd_statfs
+ */
+void
+statfs_to_freebsd_statfs(p, mp, sp, fsp)
+ struct proc *p;
+ struct mount *mp;
+ struct statfs *sp;
+ struct freebsd_statfs *fsp;
+{
+ fsp->f_bsize = sp->f_bsize;
+ fsp->f_iosize = sp->f_iosize;
+ fsp->f_blocks = sp->f_blocks;
+ fsp->f_bfree = sp->f_bfree;
+ fsp->f_bavail = sp->f_bavail;
+ fsp->f_files = sp->f_files;
+ fsp->f_ffree = sp->f_ffree;
+ /* Don't let non-root see filesystem id (for NFS security) */
+ if (suser(p->p_ucred, &p->p_acflag))
+ fsp->f_fsid.val[0] = fsp->f_fsid.val[1] = 0;
+ else
+ bcopy(&sp->f_fsid, &fsp->f_fsid, sizeof(fsp->f_fsid));
+ fsp->f_owner = sp->f_owner;
+ fsp->f_type = mp->mnt_vfc->vfc_typenum;
+ fsp->f_flags = sp->f_flags;
+ fsp->f_syncwrites = sp->f_syncwrites;
+ fsp->f_asyncwrites = sp->f_asyncwrites;
+ bcopy(sp->f_fstypename, fsp->f_fstypename, MFSNAMELEN);
+ bcopy(sp->f_mntonname, fsp->f_mntonname, MNAMELEN);
+ bcopy(sp->f_mntfromname, fsp->f_mntfromname, MNAMELEN);
+}
+
+/*
+ * Get filesystem statistics.
+ */
+/* ARGSUSED */
int
freebsd_sys_statfs(p, v, retval)
struct proc *p;
void *v;
register_t *retval;
{
- struct freebsd_sys_stat_args /* {
+ register struct freebsd_sys_statfs_args /* {
syscallarg(char *) path;
- syscallarg(struct statfs *) buf;
+ syscallarg(struct freebsd_statfs *) buf;
} */ *uap = v;
+ register struct mount *mp;
+ register struct statfs *sp;
+ struct freebsd_statfs fsb;
+ int error;
+ struct nameidata nd;
caddr_t sg = stackgap_init(p->p_emul);
FREEBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
- return sys_statfs(p, uap, retval);
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
+ if ((error = namei(&nd)) != 0)
+ return (error);
+ mp = nd.ni_vp->v_mount;
+ sp = &mp->mnt_stat;
+ vrele(nd.ni_vp);
+ if ((error = VFS_STATFS(mp, sp, p)) != 0)
+ return (error);
+ sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
+
+ statfs_to_freebsd_statfs(p, mp, sp, &fsb);
+ return (copyout((caddr_t)&fsb, (caddr_t)SCARG(uap, buf), sizeof(fsb)));
+}
+
+/*
+ * Get filesystem statistics.
+ */
+/* ARGSUSED */
+int
+freebsd_sys_fstatfs(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ register struct freebsd_sys_fstatfs_args /* {
+ syscallarg(int) fd;
+ syscallarg(struct freebsd_statfs *) buf;
+ } */ *uap = v;
+ struct file *fp;
+ struct mount *mp;
+ register struct statfs *sp;
+ struct freebsd_statfs fsb;
+ int error;
+
+ if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
+ return (error);
+ mp = ((struct vnode *)fp->f_data)->v_mount;
+ sp = &mp->mnt_stat;
+ if ((error = VFS_STATFS(mp, sp, p)) != 0)
+ return (error);
+ sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
+
+ statfs_to_freebsd_statfs(p, mp, sp, &fsb);
+ return (copyout((caddr_t)&fsb, (caddr_t)SCARG(uap, buf), sizeof(fsb)));
+}
+
+/*
+ * Get statistics on all filesystems.
+ */
+int
+freebsd_sys_getfsstat(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ register struct freebsd_sys_getfsstat_args /* {
+ syscallarg(struct freebsd_statfs *) buf;
+ syscallarg(long) bufsize;
+ syscallarg(int) flags;
+ } */ *uap = v;
+ register struct mount *mp, *nmp;
+ register struct statfs *sp;
+ struct freebsd_statfs fsb;
+ caddr_t sfsp;
+ long count, maxcount;
+ int error, flags = SCARG(uap, flags);
+
+ maxcount = SCARG(uap, bufsize) / sizeof(struct freebsd_statfs);
+ sfsp = (caddr_t)SCARG(uap, buf);
+ count = 0;
+ simple_lock(&mountlist_slock);
+ for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {
+ if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
+ nmp = mp->mnt_list.cqe_next;
+ continue;
+ }
+ if (sfsp && count < maxcount) {
+ sp = &mp->mnt_stat;
+
+ /* Refresh stats unless MNT_NOWAIT is specified */
+ if (flags != MNT_NOWAIT &&
+ flags != MNT_LAZY &&
+ (flags == MNT_WAIT ||
+ flags == 0) &&
+ (error = VFS_STATFS(mp, sp, p))) {
+ simple_lock(&mountlist_slock);
+ nmp = mp->mnt_list.cqe_next;
+ vfs_unbusy(mp, p);
+ continue;
+ }
+ sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
+
+ statfs_to_freebsd_statfs(p, mp, sp, &fsb);
+ error = copyout((caddr_t)&fsb, sfsp, sizeof(fsb));
+ if (error) {
+ vfs_unbusy(mp, p);
+ return (error);
+ }
+ sfsp += sizeof(fsb);
+ }
+ count++;
+ simple_lock(&mountlist_slock);
+ nmp = mp->mnt_list.cqe_next;
+ vfs_unbusy(mp, p);
+ }
+ simple_unlock(&mountlist_slock);
+ if (sfsp && count > maxcount)
+ *retval = maxcount;
+ else
+ *retval = count;
+ return (0);
}
#ifdef NFSCLIENT