diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/syscalls.master | 18 | ||||
-rw-r--r-- | sys/kern/vfs_bio.c | 4 | ||||
-rw-r--r-- | sys/kern/vfs_cluster.c | 4 | ||||
-rw-r--r-- | sys/kern/vfs_extattr.c | 309 | ||||
-rw-r--r-- | sys/kern/vfs_syscalls.c | 309 | ||||
-rw-r--r-- | sys/sys/mount.h | 41 | ||||
-rw-r--r-- | sys/ufs/ffs/ffs_vfsops.c | 11 |
7 files changed, 651 insertions, 45 deletions
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, |