--- sys/kern/kern_shutdown.c 2006/02/06 10:18:47 +++ sys/kern/kern_shutdown.c 2006/03/25 21:09:31 @@ -68,6 +68,12 @@ #include #include +#include +#include +#include +#include +#include + #include #ifndef PANIC_REBOOT_WAIT_TIME @@ -384,6 +390,7 @@ if (panicstr == 0) vfs_unmountall(); } + swapoff_all(); DELAY(100000); /* wait for console output to finish */ } --- sys/vm/swap_pager.c 2006/03/08 06:35:18 +++ sys/vm/swap_pager.c 2006/03/26 01:30:28 @@ -2084,69 +2084,22 @@ 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; +#ifdef MAC int error; +#endif - 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; /* @@ -2157,8 +2110,7 @@ */ if (cnt.v_free_count + cnt.v_cache_count + swap_pager_avail < nblks + nswap_lowat) { - error = ENOMEM; - goto done; + return (ENOMEM); } /* @@ -2191,11 +2143,101 @@ mtx_unlock(&sw_dev_mtx); blist_destroy(sp->sw_blist); free(sp, M_VMPGDATA); + return (0); +} + +void +swapoff_all(void) +{ + struct swdevt *sp, *spt; + const char *devname; + 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 (vn_isdisk(sp->sw_vp, NULL)) + devname = sp->sw_vp->v_rdev->si_name; + else + devname = "[file]"; + error = swapoff_one(sp, &thread0); + if (error != 0) { + printf("Cannot remove swap device %s (error=%d), " + "skipping.\n", devname, error); + } else if (bootverbose) { + printf("Swap device %s removed.\n", devname); + } + 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); } --- sys/vm/swap_pager.h 2005/01/07 02:32:16 +++ sys/vm/swap_pager.h 2006/03/25 21:09:31 @@ -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 swapoff_all(void); #endif /* _KERNEL */ #endif /* _VM_SWAP_PAGER_H_ */