cvs commit: src/sys/kern vfs_syscalls.c

John Baldwin jhb at FreeBSD.org
Fri May 27 12:36:34 PDT 2005


On Friday 27 May 2005 03:21 pm, Pawel Jakub Dawidek wrote:
> pjd         2005-05-27 19:21:08 UTC
>
>   FreeBSD src repository
>
>   Modified files:
>     sys/kern             vfs_syscalls.c
>   Log:
>   Sync locking in freebsd4_getfsstat() with getfsstat().
>   Giant is probably also needed in kern_fhstatfs().

Hmm, can you possibly hold up on this?  I have a patch to create 
kern_getfsstat() that will save you a lot of trouble if you want to test it 
at http://www.freebsd.org/~jhb/patches/getfsstat.patch and below:

--- //depot/projects/smpng/sys/alpha/osf1/osf1_mount.c	2005/05/27 14:58:46
+++ //depot/user/jhb/proc/alpha/osf1/osf1_mount.c	2005/05/27 19:03:47
@@ -156,56 +156,44 @@
 	struct thread *td;
 	register struct osf1_getfsstat_args *uap;
 {
-	long count, error, maxcount;
-	caddr_t osf_sfsp;
-	struct mount *mp, *nmp;
-	struct statfs *sp, sb;
+	struct statfs *buf, *sp;
 	struct osf1_statfs osfs;
+	size_t count, size;
+	int error, flags;
 
 	if (uap->flags & ~OSF1_GETFSSTAT_FLAGS)
 		return (EINVAL);
+	flags = 0;
+	if (uap->flags & OSF1_MNT_WAIT)
+		flags |= MNT_WAIT;
+	if (uap->flags & OSF1_MNT_NOWAIT)
+		flags |= MNT_NOWAIT;
 
-	maxcount = uap->bufsize / sizeof(struct osf1_statfs);
-	osf_sfsp = (caddr_t)uap->buf;
-	for (count = 0, mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
-		nmp = TAILQ_NEXT(mp, mnt_list);
-		if (osf_sfsp && count < maxcount) {
-			if (!prison_check_mount(td->td_ucred, mp))
-	                        continue;
-#ifdef MAC
-			if (mac_check_mount_stat(td->td_ucred, mp) != 0)
-				continue;
-#endif
-			sp = &mp->mnt_stat;
-			/*
-			 * If OSF1_MNT_NOWAIT is specified, do not refresh the
-			 * fsstat cache.  OSF1_MNT_WAIT overrides
-			 * OSF1_MNT_NOWAIT.
-			 */
-			if (((uap->flags & OSF1_MNT_NOWAIT) == 0 ||
-			    (uap->flags & OSF1_MNT_WAIT)) &&
-			    (error = VFS_STATFS(mp, sp, td)))
-				continue;
-			sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
+	count = uap->bufsize / sizeof(struct ostatfs);
+	size = count * sizeof(struct statfs);
+	if (size > 0)
+		buf = malloc(size, M_TEMP, M_WAITOK);
+	else
+		buf = NULL;
+	error = kern_getfsstat(td, buf, size, UIO_SYSSPACE, flags);
+	if (buf != NULL) {
+		count = td->td_retval[0];
+		sp = buf;
+		while (count > 0 && error != 0) {
 			if (suser(td)) {
 				bcopy(sp, &sb, sizeof(sb));
 				sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
 				sp = &sb;
 			}
 			bsd2osf_statfs(sp, &osfs);
-			if ((error = copyout(&osfs, osf_sfsp,
-			    sizeof (struct osf1_statfs))))
-				return (error);
-			osf_sfsp += sizeof (struct osf1_statfs);
+			error = copyout(&osfs, uap->buf, sizeof(osfs));
+			sp++;
+			uap->buf++;
+			count--;
 		}
-		count++;
+		free(buf, M_TEMP);
 	}
-	if (osf_sfsp && count > maxcount)
-		td->td_retval[0] = maxcount;
-	else
-		td->td_retval[0] = count;
-
-	return (0);
+	return (error);
 }
 
 int
--- //depot/projects/smpng/sys/compat/freebsd32/freebsd32_misc.c	2005/05/27 
14:58:46
+++ //depot/user/jhb/proc/compat/freebsd32/freebsd32_misc.c	2005/05/27 
19:03:47
@@ -155,32 +155,29 @@
 int
 freebsd4_freebsd32_getfsstat(struct thread *td, struct 
freebsd4_freebsd32_getfsstat_args *uap)
 {
+	struct statfs *buf, *sp;
+	struct statfs32 stat32;
+	size_t count, size;
 	int error;
-	caddr_t sg;
-	struct statfs32 *sp32, stat32;
-	struct statfs *sp = NULL, stat;
-	int maxcount, count, i;
 
-	sp32 = uap->buf;
-	maxcount = uap->bufsize / sizeof(struct statfs32);
-
-	if (sp32) {
-		sg = stackgap_init();
-		sp = stackgap_alloc(&sg, sizeof(struct statfs) * maxcount);
-		uap->buf = (struct statfs32 *)sp;
-	}
-	error = getfsstat(td, (struct getfsstat_args *) uap);
-	if (sp32 && !error) {
+	count = uap->bufsize / sizeof(struct statfs32);
+	size = count * sizeof(struct statfs);
+	if (size > 0)
+		buf = malloc(size, M_TEMP, M_WAITOK);
+	else
+		buf = NULL;
+	error = kern_getfsstat(td, buf, size, UIO_SYSSPACE, uap->flags);
+	if (buf != NULL) {
 		count = td->td_retval[0];
-		for (i = 0; i < count; i++) {
-			error = copyin(&sp[i], &stat, sizeof(stat));
-			if (error)
-				return (error);
-			copy_statfs(&stat, &stat32);
-			error = copyout(&stat32, &sp32[i], sizeof(stat32));
-			if (error)
-				return (error);
+		sp = buf;
+		while (count > 0 && error != 0) {
+			copy_statfs(sp, &stat32);
+			error = copyout(&stat32, uap->buf, sizeof(stat32));
+			sp++;
+			uap->buf++;
+			count--;
 		}
+		free(buf, M_TEMP);
 	}
 	return (error);
 }
--- //depot/projects/smpng/sys/compat/linux/linux_misc.c	2005/05/27 14:58:46
+++ //depot/user/jhb/proc/compat/linux/linux_misc.c	2005/05/27 19:03:47
--- //depot/projects/smpng/sys/kern/vfs_syscalls.c	2005/05/27 14:58:46
+++ //depot/user/jhb/proc/kern/vfs_syscalls.c	2005/05/27 19:03:47
@@ -363,13 +363,22 @@
 		int flags;
 	} */ *uap;
 {
+
+	return (kern_getfsstat(td, uap->buf, uap->bufsize, UIO_USERSPACE,
+	    uap->flags));
+}
+
+int
+kern_getfsstat(struct thread *td, struct statfs *buf, size_t bufsize,
+    enum uio_seg bufseg, int flags)
+{
 	struct mount *mp, *nmp;
-	struct statfs *sp, sb;
-	caddr_t sfsp;
-	long count, maxcount, error;
+	struct statfs *sfsp, *sp, sb;
+	size_t count, maxcount;
+	int error;
 
-	maxcount = uap->bufsize / sizeof(struct statfs);
-	sfsp = (caddr_t)uap->buf;
+	maxcount = bufsize / sizeof(struct statfs);
+	sfsp = buf;
 	count = 0;
 	mtx_lock(&Giant);
 	mtx_lock(&mountlist_mtx);
@@ -402,8 +411,8 @@
 			 * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY
 			 * overrides MNT_WAIT.
 			 */
-			if (((uap->flags & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
-			    (uap->flags & MNT_WAIT)) &&
+			if (((flags & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
+			    (flags & MNT_WAIT)) &&
 			    (error = VFS_STATFS(mp, sp, td))) {
 				mtx_lock(&mountlist_mtx);
 				nmp = TAILQ_NEXT(mp, mnt_list);
@@ -415,13 +424,16 @@
 				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);
-				mtx_unlock(&Giant);
-				return (error);
-			}
-			sfsp += sizeof(*sp);
+			if (bufseg == UIO_USERSPACE) {
+				error = copyout(sp, sfsp, sizeof(*sp));
+				if (error) {
+					vfs_unbusy(mp, td);
+					mtx_unlock(&Giant);
+					return (error);
+				}
+			} else
+				bcopy(sp, sfsp, sizeof(*sp));
+			sfsp++;
 		}
 		count++;
 		mtx_lock(&mountlist_mtx);
@@ -515,71 +527,36 @@
 		int flags;
 	} */ *uap;
 {
-	struct mount *mp, *nmp;
-	struct statfs *sp, sb;
+	struct statfs *buf, *sp;
 	struct ostatfs osb;
-	caddr_t sfsp;
-	long count, maxcount, error;
+	size_t count, size;
+	int 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) {
-		if (!prison_check_mount(td->td_ucred, mp)) {
-			nmp = TAILQ_NEXT(mp, mnt_list);
-			continue;
-		}
-#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;
+	count = uap->bufsize / sizeof(struct ostatfs);
+	size = count * sizeof(struct statfs);
+	if (size > 0)
+		buf = malloc(size, M_TEMP, M_WAITOK);
+	else
+		buf = NULL;
+	error = kern_getfsstat(td, buf, size, UIO_SYSSPACE, uap->flags);
+	if (buf != NULL) {
+		count = td->td_retval[0];
+		sp = buf;
+		while (count > 0 && error != 0) {
 			if (suser(td)) {
 				bcopy(sp, &sb, sizeof(sb));
 				sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
 				sp = &sb;
 			}
 			cvtstatfs(td, sp, &osb);
-			error = copyout(&osb, sfsp, sizeof(osb));
-			if (error) {
-				vfs_unbusy(mp, td);
-				return (error);
-			}
-			sfsp += sizeof(osb);
+			error = copyout(&osb, uap->buf, sizeof(osb));
+			sp++;
+			uap->buf++;
+			count--;
 		}
-		count++;
-		mtx_lock(&mountlist_mtx);
-		nmp = TAILQ_NEXT(mp, mnt_list);
-		vfs_unbusy(mp, td);
+		free(buf, M_TEMP);
 	}
-	mtx_unlock(&mountlist_mtx);
-	if (sfsp && count > maxcount)
-		td->td_retval[0] = maxcount;
-	else
-		td->td_retval[0] = count;
-	return (0);
+	return (error);
 }
 
 /*
--- //depot/projects/smpng/sys/sys/syscallsubr.h	2005/04/01 18:38:57
+++ //depot/user/jhb/proc/sys/syscallsubr.h	2005/04/14 15:51:26
@@ -68,6 +68,8 @@
 int	kern_fstatfs(struct thread *td, int fd, struct statfs *buf);
 int	kern_futimes(struct thread *td, int fd, struct timeval *tptr,
 	    enum uio_seg tptrseg);
+int	kern_getfsstat(struct thread *td, struct statfs *buf, size_t bufsize,
+	    enum uio_seg bufseg, int flags);
 int	kern_getitimer(struct thread *, u_int, struct itimerval *);
 int	kern_getrusage(struct thread *td, int who, struct rusage *rup);
 int	kern_getsockopt(struct thread *td, int s, int level, int name,

-- 
John Baldwin <jhb at FreeBSD.org>  <><  http://www.FreeBSD.org/~jhb/
"Power Users Use the Power to Serve"  =  http://www.FreeBSD.org


More information about the cvs-all mailing list