Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 22 Mar 2000 20:16:25 +0000 (GMT)
From:      iedowse@maths.tcd.ie
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   bin/17555: fstat(1) doesn't show memory-mapped files
Message-ID:  <200003222016.aa54468@bell.maths.tcd.ie>

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

>Number:         17555
>Category:       bin
>Synopsis:       fstat(1) doesn't show memory-mapped files
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Mar 22 12:20:01 PST 2000
>Closed-Date:
>Last-Modified:
>Originator:     Ian Dowse
>Release:        FreeBSD 3.3-STABLE i386
>Organization:
		School of Mathematics
		Trinity College, Dublin
>Environment:

	FreeBSD -current or -stable
	(patch included is for RELENG_4 or -current)

>Description:

	fstat(1) is a useful tool for determining which processes hold
	references to a filesystem - I use it frequently to help resolve
	'Device busy' errors when attempting to unmount a filesystem.

	However, files that are memory-mapped into a process's address
	space don't show up (unless the file descriptor is still open).

	The patch included below makes fstat include mmap()'d files in
	its listing of open files for each process. The word 'mmap'
	appears in the FD column to indicate that this is a mmap()'d
	file.

	Most of the logic in the new dommap() function below is taken
	from procfs_map.c.

>How-To-Repeat:

>Fix:


--- fstat.1.orig	Sun Oct 17 23:59:50 1999
+++ fstat.1	Wed Mar 22 19:56:21 2000
@@ -50,6 +50,7 @@
 .Nm Fstat
 identifies open files.
 A file is considered open by a process if it was explicitly opened,
+memory-mapped,
 is the working directory, root directory, active executable text, or kernel
 trace file for that process.
 If no options are specified,
@@ -117,6 +118,7 @@
 wd 	- current working directory
 root	- root inode
 tr	- kernel trace file
+mmap	- memory-mapped file
 .Ed
 .Pp
 If the file number is followed by an asterisk (``*''), the file is

--- fstat.c.orig	Wed Mar 22 19:33:17 2000
+++ fstat.c	Wed Mar 22 19:56:18 2000
@@ -74,6 +74,10 @@
 #include <nfs/nfsnode.h>
 
 
+#include <vm/vm.h>
+#include <vm/vm_map.h>
+#include <vm/vm_object.h>
+
 #include <net/route.h>
 #include <netinet/in.h>
 #include <netinet/in_systm.h>
@@ -100,6 +104,7 @@
 #define	CDIR	-2
 #define	RDIR	-3
 #define	TRACE	-4
+#define	MMAP	-5
 
 DEVS *devs;
 
@@ -132,6 +137,7 @@
 kvm_t *kd;
 
 void dofiles __P((struct kinfo_proc *kp));
+void dommap __P((struct kinfo_proc *kp));
 void vtrans __P((struct vnode *vp, int i, int flag));
 int  ufs_filestat __P((struct vnode *vp, struct filestat *fsp));
 int  nfs_filestat __P((struct vnode *vp, struct filestat *fsp));
@@ -246,6 +252,7 @@
 		if (p->kp_proc.p_stat == SZOMB)
 			continue;
 		dofiles(p);
+		dommap(p);
 	}
 	exit(0);
 }
@@ -267,6 +274,9 @@
 	case TRACE: \
 		printf("   tr"); \
 		break; \
+	case MMAP: \
+		printf(" mmap"); \
+		break; \
 	default: \
 		printf(" %4d", i); \
 		break; \
@@ -356,6 +366,65 @@
 			dprintf(stderr,
 				"unknown file type %d for file %d of pid %d\n",
 				file.f_type, i, Pid);
+		}
+	}
+}
+
+void
+dommap(kp)
+	struct kinfo_proc *kp;
+{
+	struct proc *p = &kp->kp_proc;
+	struct vmspace vmspace;
+	vm_map_t map;
+	struct vm_map_entry entry;
+	vm_map_entry_t entryp;
+	struct vm_object object;
+	vm_object_t objp;
+	int prot, fflags;
+
+	if (!KVM_READ(p->p_vmspace, &vmspace, sizeof(vmspace))) {
+		dprintf(stderr, "can't read vmspace at %p for pid %d\n",
+		    (void *)p->p_vmspace, Pid);
+		return;
+	}
+
+	map = &vmspace.vm_map;
+
+	for (entryp = map->header.next; entryp != &p->p_vmspace->vm_map.header;
+	    entryp = entry.next) {
+		if (!KVM_READ(entryp, &entry, sizeof(entry))) {
+			dprintf(stderr,
+			    "can't read vm_map_entry at %p for pid %d\n",
+			    (void *)entryp, Pid);
+			return;
+		}
+
+		if (entry.eflags & MAP_ENTRY_IS_SUB_MAP)
+			continue;
+
+		if ((objp = entry.object.vm_object) == NULL)
+			continue;
+
+		for (; objp; objp = object.backing_object) {
+			if (!KVM_READ(objp, &object, sizeof(object))) {
+				dprintf(stderr,
+				    "can't read vm_object at %p for pid %d\n",
+				    (void *)objp, Pid);
+				return;
+			}
+		}
+
+		prot = entry.protection;
+		fflags = (prot & VM_PROT_READ ? FREAD : 0) |
+		    (prot & VM_PROT_WRITE ? FWRITE : 0);
+
+		switch (object.type) {
+		case OBJT_VNODE:
+			vtrans((struct vnode *)object.handle, MMAP, fflags);
+			break;
+		default:
+			break;
 		}
 	}
 }

>Release-Note:
>Audit-Trail:
>Unformatted:


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




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