VMRs that map page_maps are tracked

Needed so we can remove pages or otherwise see which processes are using
which parts of a PM.
diff --git a/kern/include/mm.h b/kern/include/mm.h
index cbe5ba6..e0133fe 100644
--- a/kern/include/mm.h
+++ b/kern/include/mm.h
@@ -24,6 +24,7 @@
  * VMRs. */
 struct vm_region {
 	TAILQ_ENTRY(vm_region)		vm_link;
+	TAILQ_ENTRY(vm_region)		vm_pm_link;
 	struct proc					*vm_proc;	/* owning process, for now */
 	uintptr_t					vm_base;
 	uintptr_t					vm_end;
@@ -34,8 +35,6 @@
 };
 TAILQ_HEAD(vmr_tailq, vm_region);			/* Declares 'struct vmr_tailq' */
 
-#include <process.h>						/* preprocessor games */
-
 /* VM Region Management Functions.  For now, these just maintain themselves -
  * anything related to mapping needs to be done by the caller. */
 void vmr_init(void);
diff --git a/kern/include/pagemap.h b/kern/include/pagemap.h
index bbbed5e..0aab4e9 100644
--- a/kern/include/pagemap.h
+++ b/kern/include/pagemap.h
@@ -12,6 +12,7 @@
 
 #include <radix.h>
 #include <atomic.h>
+#include <mm.h>
 
 /* Need to be careful, due to some ghetto circular references */
 struct page;
@@ -33,6 +34,8 @@
 	struct page_map_operations	*pm_op;
 	unsigned int				pm_flags;
 	/*... and private lists, backing block dev info, other mappings, etc. */
+	spinlock_t					pm_lock;
+	struct vmr_tailq			pm_vmrs;
 };
 
 /* Operations performed on a page_map.  These are usually FS specific, which
@@ -57,5 +60,8 @@
 void pm_init(struct page_map *pm, struct page_map_operations *op, void *host);
 int pm_load_page(struct page_map *pm, unsigned long index, struct page **pp);
 void pm_put_page(struct page *page);
+void pm_add_vmr(struct page_map *pm, struct vm_region *vmr);
+void pm_remove_vmr(struct page_map *pm, struct vm_region *vmr);
+void print_page_map_info(struct page_map *pm);
 
 #endif /* ROS_KERN_PAGEMAP_H */
diff --git a/kern/src/mm.c b/kern/src/mm.c
index 29aedfc..bc231df 100644
--- a/kern/src/mm.c
+++ b/kern/src/mm.c
@@ -25,10 +25,15 @@
 #include <vfs.h>
 #include <smp.h>
 
-static int __vmr_free_pgs(struct proc *p, pte_t *pte, void *va, void *arg);
-
 struct kmem_cache *vmr_kcache;
 
+static int __vmr_free_pgs(struct proc *p, pte_t *pte, void *va, void *arg);
+/* minor helper, will ease the file->chan transition */
+static struct page_map *file2pm(struct file *file)
+{
+	return file->f_mapping;
+}
+
 void vmr_init(void)
 {
 	vmr_kcache = kmem_cache_create("vm_regions", sizeof(struct vm_region),
@@ -118,6 +123,7 @@
 		new_vmr->vm_file = old_vmr->vm_file;
 		new_vmr->vm_foff = old_vmr->vm_foff +
 		                      old_vmr->vm_end - old_vmr->vm_base;
+		pm_add_vmr(file2pm(old_vmr->vm_file), new_vmr);
 	} else {
 		new_vmr->vm_file = 0;
 		new_vmr->vm_foff = 0;
@@ -190,8 +196,10 @@
  * out the page table entries. */
 void destroy_vmr(struct vm_region *vmr)
 {
-	if (vmr->vm_file)
+	if (vmr->vm_file) {
+		pm_remove_vmr(file2pm(vmr->vm_file), vmr);
 		kref_put(&vmr->vm_file->f_kref);
+	}
 	TAILQ_REMOVE(&vmr->vm_proc->vm_regions, vmr, vm_link);
 	kmem_cache_free(vmr_kcache, vmr);
 }
@@ -322,10 +330,12 @@
 		vmr->vm_end = vm_i->vm_end;
 		vmr->vm_prot = vm_i->vm_prot;	
 		vmr->vm_flags = vm_i->vm_flags;	
-		if (vm_i->vm_file)
-			kref_get(&vm_i->vm_file->f_kref, 1);
 		vmr->vm_file = vm_i->vm_file;
 		vmr->vm_foff = vm_i->vm_foff;
+		if (vm_i->vm_file) {
+			kref_get(&vm_i->vm_file->f_kref, 1);
+			pm_add_vmr(file2pm(vm_i->vm_file), vmr);
+		}
 		if (!vmr->vm_file || vmr->vm_flags & MAP_PRIVATE) {
 			assert(!(vmr->vm_flags & MAP_SHARED));
 			/* Copy over the memory from one VMR to the other */
@@ -499,6 +509,7 @@
 	vmr->vm_flags = flags;
 	if (file) {
 		if (!check_file_perms(vmr, file, prot)) {
+			assert(!vmr->vm_file);
 			destroy_vmr(vmr);
 			set_errno(EACCES);
 			return MAP_FAILED;
@@ -514,17 +525,20 @@
 			 * immediately mprotect it to PROT_NONE. */
 			flags &= ~MAP_POPULATE;
 		}
+		/* Prep the FS to make sure it can mmap the file.  Slightly weird
+		 * semantics: if we fail and had munmapped the space, they will have a
+		 * hole in their VM now. */
+		if (file->f_op->mmap(file, vmr)) {
+			assert(!vmr->vm_file);
+			destroy_vmr(vmr);
+			set_errno(EACCES);	/* not quite */
+			return MAP_FAILED;
+		}
 		kref_get(&file->f_kref, 1);
+		pm_add_vmr(file2pm(file), vmr);
 	}
 	vmr->vm_file = file;
 	vmr->vm_foff = offset;
-	/* Prep the FS to make sure it can mmap the file.  Slightly weird semantics:
-	 * they will have a hole in their VM now. */
-	if (file && file->f_op->mmap(file, vmr)) {
-		destroy_vmr(vmr);
-		set_errno(EACCES);	/* not quite */
-		return MAP_FAILED;
-	}
 	addr = vmr->vm_base;		/* so we know which pages to populate later */
 	vmr = merge_me(vmr);		/* attempts to merge with neighbors */
 	/* Fault in pages now if MAP_POPULATE.  We want to populate the region
diff --git a/kern/src/pagemap.c b/kern/src/pagemap.c
index c984911..62e43bf 100644
--- a/kern/src/pagemap.c
+++ b/kern/src/pagemap.c
@@ -12,6 +12,23 @@
 #include <assert.h>
 #include <stdio.h>
 
+void pm_add_vmr(struct page_map *pm, struct vm_region *vmr)
+{
+	/* note that the VMR being reverse-mapped by the PM is protected by the PM's
+	 * lock.  so later when removal holds this, it delays munmaps and keeps the
+	 * VMR connected. */
+	spin_lock(&pm->pm_lock);
+	TAILQ_INSERT_TAIL(&pm->pm_vmrs, vmr, vm_pm_link);
+	spin_unlock(&pm->pm_lock);
+}
+
+void pm_remove_vmr(struct page_map *pm, struct vm_region *vmr)
+{
+	spin_lock(&pm->pm_lock);
+	TAILQ_REMOVE(&pm->pm_vmrs, vmr, vm_pm_link);
+	spin_unlock(&pm->pm_lock);
+}
+
 /* Initializes a PM.  Host should be an *inode or a *bdev (doesn't matter).  The
  * reference this stores is uncounted. */
 void pm_init(struct page_map *pm, struct page_map_operations *op, void *host)
@@ -22,6 +39,8 @@
 	pm->pm_num_pages = 0;					/* no pages in a new pm */
 	pm->pm_op = op;
 	pm->pm_flags = 0;
+	spinlock_init(&pm->pm_lock);
+	TAILQ_INIT(&pm->pm_vmrs);
 }
 
 /* Looks up the index'th page in the page map, returning an incref'd reference,
@@ -132,3 +151,17 @@
 	assert(atomic_read(&page->pg_flags) & PG_UPTODATE);
 	return 0;
 }
+
+void print_page_map_info(struct page_map *pm)
+{
+	struct vm_region *vmr_i;
+	printk("Page Map %p\n", pm);
+	printk("\tNum pages: %lu\n", pm->pm_num_pages);
+	spin_lock(&pm->pm_lock);
+	TAILQ_FOREACH(vmr_i, &pm->pm_vmrs, vm_pm_link) {
+		printk("\tVMR proc %d: (%p - %p): 0x%08x, 0x%08x, %p, %p\n",
+		       vmr_i->vm_proc->pid, vmr_i->vm_base, vmr_i->vm_end,
+		       vmr_i->vm_prot, vmr_i->vm_flags, vmr_i->vm_file, vmr_i->vm_foff);
+	}
+	spin_unlock(&pm->pm_lock);
+}