DragonFly BSD
DragonFly bugs List (threaded) for 2005-02
[Date Prev][Date Next]  [Thread Prev][Thread Next]  [Date Index][Thread Index]

(lightbulb goes off) Re: sockstat not working


From: Matthew Dillon <dillon@xxxxxxxxxxxxxxxxxxxx>
Date: Wed, 2 Feb 2005 12:34:47 -0800 (PST)

:OK - I rm -rf'ed /usr/src/*,/usr/obj/*, re-cvsup'ed from 
:dragonflybsd.org and built new world and kernel plus a reboot.
:Still the same sockstat error :-(
:
:Here is the url to the ktrace output: http://bsdtech.com/~erik/ktrace.out
:
: -Erik

    Ah ha!  I think I'm on to something here.  It looks like sysctl is being
    asked to report the buffer size but then the second call which fills the
    buffer is returning ENOMEM, meaning that the supplied buffer is not
    large enough, meaning that sysctl is not calculating the correct buffer
    size.

62308 sockstat CALL  __sysctl(0xbfbffc10,0x2,0xbfbffc18,0xbfbffc0c,0x8049f60,0x9)
 62308 sockstat RET   __sysctl 0
 62308 sockstat CALL  __sysctl(0xbfbffc18,0x2,0,0xbfbffc8c,0,0)
 62308 sockstat RET   __sysctl 0
 62308 sockstat CALL  __sysctl(0xbfbffc10,0x2,0xbfbffc18,0xbfbffc0c,0x8049f60,0x9)
 62308 sockstat RET   __sysctl 0
 62308 sockstat CALL  __sysctl(0xbfbffc18,0x2,0x8058000,0xbfbffc8c,0,0)
 62308 sockstat RET   __sysctl -1 errno 12 Cannot allocate memory

    I think what is going on is that the sysctl code in kern_descrip.c is
    not counting threaded processes (which share their descriptor tables)
    properly.

    Since your system has a lot of threaded processes, and my system doesn't,
    you are hitting the bug and I am not.

    Please try the enclosed patch.  I have committed this to HEAD as well
    and will slip the stable tag on it once I get confirmation that it
    fixes the problem.

					-Matt
					Matthew Dillon 
					<dillon@xxxxxxxxxxxxx>

Index: kern_descrip.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_descrip.c,v
retrieving revision 1.38
diff -u -r1.38 kern_descrip.c
--- kern_descrip.c	14 Jan 2005 19:28:10 -0000	1.38
+++ kern_descrip.c	2 Feb 2005 20:33:47 -0000
@@ -37,7 +37,7 @@
  *
  *	@(#)kern_descrip.c	8.6 (Berkeley) 4/19/94
  * $FreeBSD: src/sys/kern/kern_descrip.c,v 1.81.2.19 2004/02/28 00:43:31 tegge Exp $
- * $DragonFly: src/sys/kern/kern_descrip.c,v 1.38 2005/01/14 19:28:10 dillon Exp $
+ * $DragonFly$
  */
 
 #include "opt_compat.h"
@@ -1708,7 +1708,9 @@
 	struct filedesc *fdp;
 	struct file *fp;
 	struct proc *p;
-	int error, n;
+	int count;
+	int error;
+	int n;
 
 	/*
 	 * Note: because the number of file descriptors is calculated
@@ -1716,35 +1718,47 @@
 	 * there is information leakage from the first loop.  However,
 	 * it is of a similar order of magnitude to the leakage from
 	 * global system statistics such as kern.openfiles.
+	 *
+	 * When just doing a count, note that we cannot just count
+	 * the elements and add f_count via the filehead list because 
+	 * threaded processes share their descriptor table and f_count might
+	 * still be '1' in that case.
 	 */
-	if (req->oldptr == NULL) {
-		n = 16;		/* A slight overestimate. */
-		LIST_FOREACH(fp, &filehead, f_list)
-			n += fp->f_count;
-		return (SYSCTL_OUT(req, 0, n * sizeof(kf)));
-	}
+	count = 0;
 	error = 0;
 	LIST_FOREACH(p, &allproc, p_list) {
 		if (p->p_stat == SIDL)
 			continue;
-		if (!PRISON_CHECK(req->td->td_proc->p_ucred, p->p_ucred) != 0) {
+		if (!PRISON_CHECK(req->td->td_proc->p_ucred, p->p_ucred) != 0)
 			continue;
-		}
-		if ((fdp = p->p_fd) == NULL) {
+		if ((fdp = p->p_fd) == NULL)
 			continue;
-		}
 		for (n = 0; n < fdp->fd_nfiles; ++n) {
 			if ((fp = fdp->fd_ofiles[n]) == NULL)
 				continue;
-			kcore_make_file(&kf, fp, p->p_pid,
-					p->p_ucred->cr_uid, n);
-			error = SYSCTL_OUT(req, &kf, sizeof(kf));
-			if (error)
-				break;
+			if (req->oldptr == NULL) {
+				++count;
+			} else {
+				kcore_make_file(&kf, fp, p->p_pid,
+						p->p_ucred->cr_uid, n);
+				error = SYSCTL_OUT(req, &kf, sizeof(kf));
+				if (error)
+					break;
+			}
 		}
 		if (error)
 			break;
 	}
+
+	/*
+	 * When just calculating the size, overestimate a bit to try to
+	 * prevent system activity from causing the buffer-fill call 
+	 * to fail later on.
+	 */
+	if (req->oldptr == NULL) {
+		count = (count + 16) + (count / 10);
+		error = SYSCTL_OUT(req, NULL, count * sizeof(kf));
+	}
 	return (error);
 }
 



[Date Prev][Date Next]  [Thread Prev][Thread Next]  [Date Index][Thread Index]