diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 1999-05-31 17:34:56 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 1999-05-31 17:34:56 +0000 |
commit | bc8362e4ef1c185f7c1d9aec69d91f269c97d4e2 (patch) | |
tree | 9194d1773b772347d76766611948ee38e1002058 /sys/compat/freebsd/freebsd_file.c | |
parent | 7a1b6dcd69cb5defd76dca41d6f8252a3140fb91 (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.c | 181 |
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 |