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/kern/vfs_syscalls.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/kern/vfs_syscalls.c')
-rw-r--r-- | sys/kern/vfs_syscalls.c | 183 |
1 files changed, 177 insertions, 6 deletions
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 46eca31aab0..f2f2892bb74 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_syscalls.c,v 1.56 1999/02/26 04:51:17 art Exp $ */ +/* $OpenBSD: vfs_syscalls.c,v 1.57 1999/05/31 17:34:48 millert Exp $ */ /* $NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $ */ /* @@ -70,6 +70,7 @@ int usermount = 0; /* sysctl: by default, users may not mount */ static int change_dir __P((struct nameidata *, struct proc *)); void checkdirs __P((struct vnode *)); +void statfs_to_ostatfs __P((struct proc *, struct mount *, struct statfs *, struct ostatfs *)); /* * Redirection info so we don't have to include the union fs routines in @@ -248,7 +249,6 @@ sys_mount(p, v, retval) vfs_busy(mp, LK_NOWAIT, 0, p); mp->mnt_op = vfsp->vfc_vfsops; mp->mnt_vfc = vfsp; - mp->mnt_stat.f_type = vfsp->vfc_typenum; mp->mnt_flag |= (vfsp->vfc_flags & MNT_VISFLAGMASK); strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN); mp->mnt_vnodecovered = vp; @@ -643,15 +643,15 @@ sys_getfsstat(p, v, retval) { register struct sys_getfsstat_args /* { syscallarg(struct statfs *) buf; - syscallarg(long) bufsize; + syscallarg(size_t) bufsize; syscallarg(int) flags; } */ *uap = v; register struct mount *mp, *nmp; register struct statfs *sp; - caddr_t sfsp; - long count, maxcount, error; struct statfs sb; - int flags = SCARG(uap, flags); + caddr_t sfsp; + size_t count, maxcount; + int error, flags = SCARG(uap, flags); maxcount = SCARG(uap, bufsize) / sizeof(struct statfs); sfsp = (caddr_t)SCARG(uap, buf); @@ -2360,3 +2360,174 @@ getvnode(fdp, fd, fpp) *fpp = fp; return (0); } + +/* + * At some point (before 2.6 is released), these will move to + * sys/compat/vfs_syscalls_25.c + */ + +/* + * Convert struct statfs -> struct ostatfs + */ +void +statfs_to_ostatfs(p, mp, sp, osp) + struct proc *p; + struct mount *mp; + struct statfs *sp; + struct ostatfs *osp; +{ +#if defined(COMPAT_09) || defined(COMPAT_43) + osp->f_type = mp->mnt_vfc->vfc_typenum; +#else + osp->f_type = 0; +#endif + osp->f_flags = mp->mnt_flag & 0xffff; + osp->f_bsize = sp->f_bsize; + osp->f_iosize = sp->f_iosize; + osp->f_blocks = sp->f_blocks; + osp->f_bfree = sp->f_bfree; + osp->f_bavail = sp->f_bavail; + osp->f_files = sp->f_files; + osp->f_ffree = sp->f_ffree; + /* Don't let non-root see filesystem id (for NFS security) */ + if (suser(p->p_ucred, &p->p_acflag)) + osp->f_fsid.val[0] = osp->f_fsid.val[1] = 0; + else + bcopy(&sp->f_fsid, &osp->f_fsid, sizeof(osp->f_fsid)); + osp->f_owner = sp->f_owner; + osp->f_syncwrites = sp->f_syncwrites; + osp->f_asyncwrites = sp->f_asyncwrites; + bcopy(sp->f_fstypename, osp->f_fstypename, MFSNAMELEN); + bcopy(sp->f_mntonname, osp->f_mntonname, MNAMELEN); + bcopy(sp->f_mntfromname, osp->f_mntfromname, MNAMELEN); +} + +/* + * Get filesystem statistics. + */ +/* ARGSUSED */ +int +sys_ostatfs(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + register struct sys_ostatfs_args /* { + syscallarg(char *) path; + syscallarg(struct ostatfs *) buf; + } */ *uap = v; + register struct mount *mp; + register struct statfs *sp; + struct ostatfs osb; + int error; + struct nameidata nd; + + 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); + + statfs_to_ostatfs(p, mp, sp, &osb); + return (copyout((caddr_t)&osb, (caddr_t)SCARG(uap, buf), sizeof(osb))); +} + +/* + * Get filesystem statistics. + */ +/* ARGSUSED */ +int +sys_ofstatfs(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + register struct sys_ofstatfs_args /* { + syscallarg(int) fd; + syscallarg(struct ostatfs *) buf; + } */ *uap = v; + struct file *fp; + struct mount *mp; + register struct statfs *sp; + struct ostatfs osb; + 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); + + statfs_to_ostatfs(p, mp, sp, &osb); + return (copyout((caddr_t)&osb, (caddr_t)SCARG(uap, buf), sizeof(osb))); +} + +/* + * Get statistics on all filesystems. + */ +int +sys_ogetfsstat(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + register struct sys_ogetfsstat_args /* { + syscallarg(struct ostatfs *) buf; + syscallarg(long) bufsize; + syscallarg(int) flags; + } */ *uap = v; + register struct mount *mp, *nmp; + register struct statfs *sp; + struct ostatfs osb; + caddr_t sfsp; + long count, maxcount; + int error, flags = SCARG(uap, flags); + + maxcount = SCARG(uap, bufsize) / sizeof(struct ostatfs); + 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; + } + + statfs_to_ostatfs(p, mp, sp, &osb); + error = copyout((caddr_t)&osb, sfsp, sizeof(osb)); + if (error) { + vfs_unbusy(mp, p); + return (error); + } + sfsp += sizeof(osb); + } + 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); +} |