[RFC] [PATCH] VM & VFS changes

Andre Guibert de Bruet andy at siliconlandmark.com
Tue May 31 21:24:35 PDT 2005


Hi,

I would like to present a unified set of VM and VFS diffs for wider 
scrutiny and testing. I have been running these diffs since May 10th 
across daily reboots with no issues.

What this patch does:
- Adds code that cleanly unmounts swaps (Forcing page-in first) after the 
final sync but before all of the filesystems are unmounted. This causes 
references to swap slices in devfs to not be dangling when the machine is 
rebooted.
- Defers unmounting of devfs until all other filesystems are unmounted.
- Prints diagnostic messages when non-free dangling vnodes are still 
active on shutdown.

What it doesn't:
- Fix the EBUSY error code that is returned on reboot (But it sharply 
reduces the amount of dangling vnodes. I am still working on this issue).
- Vacuum your apartment (Sorry...).

The patch is attached to this email. Just in case it doesn't make it to 
the list, it can also be found online at:
http://bling.properkernel.com/freebsd/vm+vfs.shutdown.changes.patch

Comments and constructive criticism very welcome. :-)

Cheers,
Andy

PS: This work was sponsored by my employer, Silicon Landmark. If you like 
what you see, support us.

/*  Andre Guibert de Bruet  * 6f43 6564 7020 656f 2e74 4220 7469 6a20 */
/*   Code poet / Sysadmin   * 636f 656b 2e79 5320 7379 6461 696d 2e6e */
/*   GSM: +1 734 846 8758   * 5520 494e 2058 6c73 7565 6874 002e 0000 */
/* WWW: siliconlandmark.com *      Tormenting bytes since 1980.       */
-------------- next part --------------
Index: kern/kern_shutdown.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_shutdown.c,v
retrieving revision 1.174
diff -u -r1.174 kern_shutdown.c
--- kern/kern_shutdown.c	12 Apr 2005 05:45:58 -0000	1.174
+++ kern/kern_shutdown.c	10 May 2005 17:09:02 -0000
@@ -64,6 +64,9 @@
 #include <sys/sysctl.h>
 #include <sys/sysproto.h>
 
+#include <vm/vm.h>
+#include <vm/swap_pager.h>
+
 #include <machine/cpu.h>
 #include <machine/pcb.h>
 #include <machine/smp.h>
@@ -374,6 +377,12 @@
 			if (!first_buf_printf)
 				printf("Final sync complete\n");
 			/*
+			 * Disable swapping
+			 */
+			if (panicstr == 0)
+				swap_swapoff_all(curthread);
+
+			/*
 			 * Unmount filesystems
 			 */
 			if (panicstr == 0)
Index: kern/vfs_subr.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/vfs_subr.c,v
retrieving revision 1.624
diff -u -r1.624 vfs_subr.c
--- kern/vfs_subr.c	6 May 2005 02:48:20 -0000	1.624
+++ kern/vfs_subr.c	11 May 2005 01:04:03 -0000
@@ -2660,6 +2660,7 @@
 {
 	struct mount *mp;
 	struct thread *td;
+	struct vnode *vp;
 	int error;
 
 	KASSERT(curthread != NULL, ("vfs_unmountall: NULL curthread"));
@@ -2669,6 +2670,39 @@
 	 */
 	while(!TAILQ_EMPTY(&mountlist)) {
 		mp = TAILQ_LAST(&mountlist, mntlist);
+
+#ifdef DIAGNOSTIC
+		printf("vfs_unmountall: TAILQ_LAST gave us: %s\n",
+			mp->mnt_stat.f_mntfromname);
+#endif /* DIAGNOSTIC */
+
+		if(!strcmp(mp->mnt_stat.f_mntfromname, "devfs") &&
+			TAILQ_FIRST(&mountlist) !=
+			TAILQ_LAST(&mountlist, mntlist))
+		{
+			mp = TAILQ_PREV(mp, mntlist, mnt_list);
+			printf("vfs_unmount_all: Found devfs. "
+				"deferring unmount.\n");
+		}
+
+#ifdef DIAGNOSTIC
+		printf("vfs_unmountall: unmounting: %s\n",
+			mp->mnt_stat.f_mntfromname);
+#endif /* DIAGNOSTIC */
+
+		if(!strcmp(mp->mnt_stat.f_mntfromname, "devfs"))
+		{
+			TAILQ_FOREACH(vp, &mp->mnt_nvnodelist, v_nmntvnodes)
+			{
+				if(!(vp->v_vflag & VI_FREE))
+					 /*vp->v_usecount > 0)*/
+				{
+					vn_printf(vp, "%s", "");
+					/*VOP_DESTROYVOBJECT(vp);*/
+				}
+			}
+		}
+
 		error = dounmount(mp, MNT_FORCE, td);
 		if (error) {
 			TAILQ_REMOVE(&mountlist, mp, mnt_list);
@@ -2682,6 +2716,9 @@
 			/* The unmount has removed mp from the mountlist */
 		}
 	}
+#ifdef DIAGNOSTIC
+	printf("vfs_unmountall(): done!\n");
+#endif /* DIAGNOSTIC */
 }
 
 /*
Index: vm/swap_pager.c
===================================================================
RCS file: /home/ncvs/src/sys/vm/swap_pager.c,v
retrieving revision 1.273
diff -u -r1.273 swap_pager.c
--- vm/swap_pager.c	20 May 2005 21:26:05 -0000	1.273
+++ vm/swap_pager.c	24 May 2005 02:21:30 -0000
@@ -2193,6 +2193,60 @@
 	return (error);
 }
 
+
+
+/*
+ * swap_swapoff_all(thread) - Disable all swap for system shutdown. This
+ * function exists because of the bad design of swapoff with its requirement
+ * for a pathname instead of a swap index. To get around the overhead of VFS
+ * lookups, we iterate through the swap tailq, force page-ins then remove the
+ * reference to each sw in queue.
+ */
+void
+swap_swapoff_all(struct thread *td)
+{
+	struct swdevt *sp;
+
+	/* printf("swap_swapoff_all: called!\n"); */
+	KASSERT((nswapdev > -1), ("nswapdev is negative: %i", nswapdev));
+
+	mtx_lock(&sw_dev_mtx);
+	sp = TAILQ_FIRST(&swtailq);
+
+	while (nswapdev)
+	{
+		/* XXX When the system is going down, it should be safe to page
+		 * anything on swap back in without any issues, as all user
+		 * processes have been killed off.
+		 */
+		sp->sw_flags |= SW_CLOSING;
+		mtx_unlock(&sw_dev_mtx);
+		
+		/*printf("swap_swapoff_all: Iterating in loop...\n"); */
+		swap_pager_swapoff(sp);
+
+		sp->sw_close(td, sp);
+		sp->sw_id = NULL;
+
+		nswapdev--;
+
+		mtx_lock(&sw_dev_mtx);
+		TAILQ_REMOVE(&swtailq, sp, sw_list);
+
+		sp = TAILQ_FIRST(&swtailq);
+		free(sp, M_VMPGDATA);
+	}
+	mtx_unlock(&sw_dev_mtx);
+
+	swap_pager_full = 2;
+	swap_pager_almost_full = 1;
+	swdevhd = NULL;
+	
+	/* printf("swap_swapoff_all: done!\n"); */
+}
+
+
+
 void
 swap_pager_status(int *total, int *used)
 {
Index: vm/swap_pager.h
===================================================================
RCS file: /home/ncvs/src/sys/vm/swap_pager.h,v
retrieving revision 1.50
diff -u -r1.50 swap_pager.h
--- vm/swap_pager.h	7 Jan 2005 02:29:27 -0000	1.50
+++ vm/swap_pager.h	10 May 2005 17:54:41 -0000
@@ -50,6 +50,7 @@
 int swap_pager_isswapped(vm_object_t, struct swdevt *);
 int swap_pager_reserve(vm_object_t, vm_pindex_t, vm_size_t);
 void swap_pager_status(int *total, int *used);
+void swap_swapoff_all(struct thread *);
 
 #endif				/* _KERNEL */
 #endif				/* _VM_SWAP_PAGER_H_ */


More information about the freebsd-current mailing list