Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 5 Aug 2006 20:17:38 -0600 (MDT)
From:      "Justin T. Gibbs" <gibbs@scsiguy.com>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   i386/101453: linprocfs disallows non-zero file offsets for maps files
Message-ID:  <200608060217.k762Hcqs023158@ns1.scsiguy.com>
Resent-Message-ID: <200608060220.k762KEQu015581@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         101453
>Category:       i386
>Synopsis:       linprocfs disallows non-zero file offsets for maps files
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-i386
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun Aug 06 02:20:14 GMT 2006
>Closed-Date:
>Last-Modified:
>Originator:     Justin T. Gibbs
>Release:        FreeBSD 6.1-STABLE i386
>Organization:
>Environment:
System: FreeBSD aslan.scsiguy.com 6.1-STABLE FreeBSD 6.1-STABLE #4: Sat May 6 17:23:37 MDT 2006 gibbs@aslan.scsiguy.com:/usr/obj/usr/src/sys/ASLAN i386

>Description:
	While trying to run Matlab R2006a under linux emulation, its
	embedded JVM complained of being unable to locate the position
	of thread stacks.  The JRE uses the linux procfs filesystem's
	"maps" file to determine this information.  Using ktrace I
	determined that the JRE was reading the maps file in 4k chunks,
	but that the output for the matlab process was much larger than
	this and was being truncated.  The attached patch allows the
	maps file to be read in chunks rather than all at once.  After
	applying this patch, the ktrace output indicated that all data
	was read correctly and the JVM error dissappeared.  Unfortunately,
	Matlab still hangs when attempting to launch its java based GUI.
	I'm still investigating that issue, but currently believe that
	the root cause for that is elsewhere in our compatibility framework.

>How-To-Repeat:
	Attempt to read the maps file in linprocfs in multiple chunks.
	
>Fix:
Index: linprocfs.c
===================================================================
RCS file: /usr/cvs/src/sys/compat/linprocfs/linprocfs.c,v
retrieving revision 1.89.2.3
diff -u -r1.89.2.3 linprocfs.c
--- linprocfs.c	3 Jul 2006 06:38:53 -0000	1.89.2.3
+++ linprocfs.c	26 Jul 2006 02:35:11 -0000
@@ -851,12 +851,14 @@
 	vm_object_t obj, tobj, lobj;
 	vm_ooffset_t off = 0;
 	char *name = "", *freename = NULL;
+	char *bufptr;
 	size_t len;
 	ino_t ino;
 	int ref_count, shadow_count, flags;
 	int error;
 	struct vnode *vp;
 	struct vattr vat;
+	off_t cur_offset;
 	
 	PROC_LOCK(p);
 	error = p_candebug(td, p);
@@ -867,10 +869,8 @@
 	if (uio->uio_rw != UIO_READ)
 		return (EOPNOTSUPP);
 	
-	if (uio->uio_offset != 0)
-		return (0);
-	
 	error = 0;
+	cur_offset = 0;
 	if (map != &curthread->td_proc->p_vmspace->vm_map)
 		vm_map_lock_read(map);
         for (entry = map->header.next;
@@ -924,12 +924,35 @@
 		if (freename)
 			free(freename, M_TEMP);
 		len = strlen(mebuffer);
+		bufptr = mebuffer;
+		if (cur_offset < uio->uio_offset) {
+			off_t delta;
+
+			/*
+			 * Discard data until we get to the
+			 * desired offset in the data.
+			 */
+			delta = uio->uio_offset - cur_offset;
+			if (delta >= len) {
+				cur_offset += len;
+				continue;
+			}
+			bufptr += delta;
+			len -= delta;
+		}
+	
 		if (len > uio->uio_resid)
 			len = uio->uio_resid; /*
 					       * XXX We should probably return
 					       * EFBIG here, as in procfs.
 					       */
-		error = uiomove(mebuffer, len, uio);
+		error = uiomove(bufptr, len, uio);
+		/*
+		 * Once we start outputing data, there is no need to
+		 * look for where the data will start, so keep
+		 * cur_offset in sync with the offset in the uio struct.
+		 */
+		cur_offset = uio->uio_offset;
 		if (error)
 			break;
 	}
>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200608060217.k762Hcqs023158>