[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