Index: kern/kern_shutdown.c =================================================================== RCS file: /private/FreeBSD/src/sys/kern/kern_shutdown.c,v retrieving revision 1.167 diff -u -p -r1.167 kern_shutdown.c --- kern/kern_shutdown.c 4 Oct 2004 13:13:23 -0000 1.167 +++ kern/kern_shutdown.c 6 Oct 2004 21:06:07 -0000 @@ -68,6 +68,12 @@ __FBSDID("$FreeBSD: src/sys/kern/kern_sh #include #include +#include +#include +#include +#include +#include + #include #ifndef PANIC_REBOOT_WAIT_TIME @@ -370,6 +376,7 @@ boot(int howto) if (panicstr == 0) vfs_unmountall(); } + swapoff_all(); DELAY(100000); /* wait for console output to finish */ } Index: vm/swap_pager.h =================================================================== RCS file: /private/FreeBSD/src/sys/vm/swap_pager.h,v retrieving revision 1.49 diff -u -p -r1.49 swap_pager.h --- vm/swap_pager.h 6 Apr 2004 20:15:36 -0000 1.49 +++ vm/swap_pager.h 6 Oct 2004 20:34:39 -0000 @@ -50,6 +50,7 @@ void swap_pager_swap_init(void); 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 swapoff_all(void); #endif /* _KERNEL */ #endif /* _VM_SWAP_PAGER_H_ */ Index: vm/swap_pager.c =================================================================== RCS file: /private/FreeBSD/src/sys/vm/swap_pager.c,v retrieving revision 1.257 diff -u -p -r1.257 swap_pager.c --- vm/swap_pager.c 24 Sep 2004 16:04:20 -0000 1.257 +++ vm/swap_pager.c 6 Oct 2004 21:48:33 -0000 @@ -2144,69 +2144,21 @@ swaponsomething(struct vnode *vp, void * mtx_unlock(&sw_dev_mtx); } -/* - * SYSCALL: swapoff(devname) - * - * Disable swapping on the given device. - * - * XXX: Badly designed system call: it should use a device index - * rather than filename as specification. We keep sw_vp around - * only to make this work. - */ -#ifndef _SYS_SYSPROTO_H_ -struct swapoff_args { - char *name; -}; -#endif - -/* - * MPSAFE - */ -/* ARGSUSED */ -int -swapoff(struct thread *td, struct swapoff_args *uap) +static int +swapoff_one(struct swdevt *sp, struct thread *td) { - struct vnode *vp; - struct nameidata nd; - struct swdevt *sp; u_long nblks, dvbase; int error; - mtx_lock(&Giant); - - error = suser(td); - if (error) - goto done2; - - while (swdev_syscall_active) - tsleep(&swdev_syscall_active, PUSER - 1, "swpoff", 0); - swdev_syscall_active = 1; - - NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->name, td); - error = namei(&nd); - if (error) - goto done; - NDFREE(&nd, NDF_ONLY_PNBUF); - vp = nd.ni_vp; - - mtx_lock(&sw_dev_mtx); - TAILQ_FOREACH(sp, &swtailq, sw_list) { - if (sp->sw_vp == vp) - goto found; - } - mtx_unlock(&sw_dev_mtx); - error = EINVAL; - goto done; -found: - mtx_unlock(&sw_dev_mtx); + mtx_assert(&Giant, MA_OWNED); #ifdef MAC - (void) vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); - error = mac_check_system_swapoff(td->td_ucred, vp); - (void) VOP_UNLOCK(vp, 0, td); + (void) vn_lock(sp->sw_vp, LK_EXCLUSIVE | LK_RETRY, td); + error = mac_check_system_swapoff(td->td_ucred, sp->sw_vp); + (void) VOP_UNLOCK(sp->sw_vp, 0, td); if (error != 0) - goto done; + return (error); #endif - + nblks = sp->sw_nblks; /* @@ -2217,8 +2169,7 @@ found: */ if (cnt.v_free_count + cnt.v_cache_count + swap_pager_avail < nblks + nswap_lowat) { - error = ENOMEM; - goto done; + return (ENOMEM); } /* @@ -2254,11 +2205,105 @@ found: mtx_unlock(&sw_dev_mtx); blist_destroy(sp->sw_blist); free(sp, M_VMPGDATA); + return (0); +} + +void +swapoff_all(void) +{ + struct swdevt *sp, *spt; + struct cdev *dev = NULL; + int error; + + mtx_lock(&Giant); + while (swdev_syscall_active) + tsleep(&swdev_syscall_active, PUSER - 1, "swpoff", 0); + swdev_syscall_active = 1; + + mtx_lock(&sw_dev_mtx); + TAILQ_FOREACH_SAFE(sp, &swtailq, sw_list, spt) { + mtx_unlock(&sw_dev_mtx); + if (bootverbose) { + dev = findcdev(sp->sw_dev); + KASSERT(dev != NULL, ("No device for swap partition.")); + } + error = swapoff_one(sp, &thread0); + if (bootverbose) { + if (error == 0) { + printf("Swap device %s removed.\n", + dev->si_name); + } else { + printf("Cannot remove swap device %s " + "(error=%d), skipping.\n", dev->si_name, + error); + } + } + mtx_lock(&sw_dev_mtx); + } + mtx_unlock(&sw_dev_mtx); + + swdev_syscall_active = 0; + wakeup_one(&swdev_syscall_active); + mtx_unlock(&Giant); +} + +/* + * SYSCALL: swapoff(devname) + * + * Disable swapping on the given device. + * + * XXX: Badly designed system call: it should use a device index + * rather than filename as specification. We keep sw_vp around + * only to make this work. + */ +#ifndef _SYS_SYSPROTO_H_ +struct swapoff_args { + char *name; +}; +#endif +/* + * MPSAFE + */ +/* ARGSUSED */ +int +swapoff(struct thread *td, struct swapoff_args *uap) +{ + struct vnode *vp; + struct nameidata nd; + struct swdevt *sp; + int error; + + error = suser(td); + if (error) + return (error); + + mtx_lock(&Giant); + while (swdev_syscall_active) + tsleep(&swdev_syscall_active, PUSER - 1, "swpoff", 0); + swdev_syscall_active = 1; + + NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->name, td); + error = namei(&nd); + if (error) + goto done; + NDFREE(&nd, NDF_ONLY_PNBUF); + vp = nd.ni_vp; + + mtx_lock(&sw_dev_mtx); + TAILQ_FOREACH(sp, &swtailq, sw_list) { + if (sp->sw_vp == vp) + break; + } + mtx_unlock(&sw_dev_mtx); + if (sp == NULL) { + error = EINVAL; + goto done; + } + error = swapoff_one(sp, td); done: swdev_syscall_active = 0; wakeup_one(&swdev_syscall_active); -done2: mtx_unlock(&Giant); return (error); }