Index: head/sys/compat/freebsd32/freebsd32_misc.c =================================================================== --- head/sys/compat/freebsd32/freebsd32_misc.c +++ head/sys/compat/freebsd32/freebsd32_misc.c @@ -253,9 +253,8 @@ count = uap->bufsize / sizeof(struct statfs32); size = count * sizeof(struct statfs); - error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags); + error = kern_getfsstat(td, &buf, size, &count, UIO_SYSSPACE, uap->flags); if (size > 0) { - count = td->td_retval[0]; sp = buf; while (count > 0 && error == 0) { copy_statfs(sp, &stat32); @@ -266,6 +265,8 @@ } free(buf, M_TEMP); } + if (error == 0) + td->td_retval[0] = count; return (error); } #endif Index: head/sys/compat/linprocfs/linprocfs.c =================================================================== --- head/sys/compat/linprocfs/linprocfs.c +++ head/sys/compat/linprocfs/linprocfs.c @@ -53,10 +53,10 @@ #include #include #include +#include #include #include #include -#include #include #include #include @@ -67,6 +67,7 @@ #include #include #include +#include #include #include #include @@ -326,11 +327,12 @@ linprocfs_domtab(PFS_FILL_ARGS) { struct nameidata nd; - struct mount *mp; const char *lep; char *dlep, *flep, *mntto, *mntfrom, *fstype; size_t lep_len; int error; + struct statfs *buf, *sp; + size_t count; /* resolve symlinks etc. in the emulation tree prefix */ NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, linux_emul_path, td); @@ -344,20 +346,26 @@ } lep_len = strlen(lep); - mtx_lock(&mountlist_mtx); - error = 0; - TAILQ_FOREACH(mp, &mountlist, mnt_list) { + buf = NULL; + error = kern_getfsstat(td, &buf, SIZE_T_MAX, &count, + UIO_SYSSPACE, MNT_WAIT); + if (error != 0) { + free(buf, M_TEMP); + free(flep, M_TEMP); + return (error); + } + + for (sp = buf; count > 0; sp++, count--) { /* determine device name */ - mntfrom = mp->mnt_stat.f_mntfromname; + mntfrom = sp->f_mntfromname; /* determine mount point */ - mntto = mp->mnt_stat.f_mntonname; - if (strncmp(mntto, lep, lep_len) == 0 && - mntto[lep_len] == '/') + mntto = sp->f_mntonname; + if (strncmp(mntto, lep, lep_len) == 0 && mntto[lep_len] == '/') mntto += lep_len; /* determine fs type */ - fstype = mp->mnt_stat.f_fstypename; + fstype = sp->f_fstypename; if (strcmp(fstype, pn->pn_info->pi_name) == 0) mntfrom = fstype = "proc"; else if (strcmp(fstype, "procfs") == 0) @@ -365,16 +373,16 @@ if (strcmp(fstype, "linsysfs") == 0) { sbuf_printf(sb, "/sys %s sysfs %s", mntto, - mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw"); + sp->f_flags & MNT_RDONLY ? "ro" : "rw"); } else { /* For Linux msdosfs is called vfat */ if (strcmp(fstype, "msdosfs") == 0) fstype = "vfat"; sbuf_printf(sb, "%s %s %s %s", mntfrom, mntto, fstype, - mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw"); + sp->f_flags & MNT_RDONLY ? "ro" : "rw"); } #define ADD_OPTION(opt, name) \ - if (mp->mnt_stat.f_flags & (opt)) sbuf_printf(sb, "," name); + if (sp->f_flags & (opt)) sbuf_printf(sb, "," name); ADD_OPTION(MNT_SYNCHRONOUS, "sync"); ADD_OPTION(MNT_NOEXEC, "noexec"); ADD_OPTION(MNT_NOSUID, "nosuid"); @@ -387,7 +395,8 @@ /* a real Linux mtab will also show NFS options */ sbuf_printf(sb, " 0 0\n"); } - mtx_unlock(&mountlist_mtx); + + free(buf, M_TEMP); free(flep, M_TEMP); return (error); } Index: head/sys/kern/vfs_syscalls.c =================================================================== --- head/sys/kern/vfs_syscalls.c +++ head/sys/kern/vfs_syscalls.c @@ -434,9 +434,14 @@ int flags; } */ *uap; { + size_t count; + int error; - return (kern_getfsstat(td, &uap->buf, uap->bufsize, UIO_USERSPACE, - uap->flags)); + error = kern_getfsstat(td, &uap->buf, uap->bufsize, &count, + UIO_USERSPACE, uap->flags); + if (error == 0) + td->td_retval[0] = count; + return (error); } /* @@ -446,7 +451,7 @@ */ int kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize, - enum uio_seg bufseg, int flags) + size_t *countp, enum uio_seg bufseg, int flags) { struct mount *mp, *nmp; struct statfs *sfsp, *sp, sb; @@ -533,9 +538,9 @@ } mtx_unlock(&mountlist_mtx); if (sfsp && count > maxcount) - td->td_retval[0] = maxcount; + *countp = maxcount; else - td->td_retval[0] = count; + *countp = count; return (0); } @@ -624,9 +629,9 @@ count = uap->bufsize / sizeof(struct ostatfs); size = count * sizeof(struct statfs); - error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags); + error = kern_getfsstat(td, &buf, size, &count, UIO_SYSSPACE, + uap->flags); if (size > 0) { - count = td->td_retval[0]; sp = buf; while (count > 0 && error == 0) { cvtstatfs(sp, &osb); @@ -637,6 +642,8 @@ } free(buf, M_TEMP); } + if (error == 0) + td->td_retval[0] = count; return (error); } Index: head/sys/sys/syscallsubr.h =================================================================== --- head/sys/sys/syscallsubr.h +++ head/sys/sys/syscallsubr.h @@ -104,7 +104,7 @@ int kern_getdirentries(struct thread *td, int fd, char *buf, u_int count, long *basep, ssize_t *residp, enum uio_seg bufseg); int kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize, - enum uio_seg bufseg, int flags); + size_t *countp, enum uio_seg bufseg, int flags); int kern_getitimer(struct thread *, u_int, struct itimerval *); int kern_getppid(struct thread *); int kern_getpeername(struct thread *td, int fd, struct sockaddr **sa,