From ca3f23ca3477d7ab916b941037bef1d1928d7804 Mon Sep 17 00:00:00 2001 From: pjd Date: Mon, 10 Apr 2006 10:03:41 +0000 Subject: On shutdown try to turn off all swap devices. This way GEOM providers are properly closed on shutdown. Requested by: ru Reviewed by: alc MFC after: 2 weeks --- sys/vm/swap_pager.c | 81 ++++++++++++++++++++++++++++++++++++++++------------- sys/vm/swap_pager.h | 1 + 2 files changed, 63 insertions(+), 19 deletions(-) (limited to 'sys/vm') diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c index e34e336..75400ff 100644 --- a/sys/vm/swap_pager.c +++ b/sys/vm/swap_pager.c @@ -265,6 +265,7 @@ SYSCTL_INT(_vm, OID_AUTO, dmmax, static void swp_sizecheck(void); static void swp_pager_async_iodone(struct buf *bp); static int swapongeom(struct thread *, struct vnode *); +static int swapoff_one(struct swdevt *sp, struct thread *td); static int swaponvp(struct thread *, struct vnode *, u_long); /* @@ -2109,15 +2110,13 @@ swapoff(struct thread *td, struct swapoff_args *uap) 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; + return (error); + mtx_lock(&Giant); while (swdev_syscall_active) tsleep(&swdev_syscall_active, PUSER - 1, "swpoff", 0); swdev_syscall_active = 1; @@ -2132,21 +2131,37 @@ swapoff(struct thread *td, struct swapoff_args *uap) mtx_lock(&sw_dev_mtx); TAILQ_FOREACH(sp, &swtailq, sw_list) { if (sp->sw_vp == vp) - goto found; + break; } mtx_unlock(&sw_dev_mtx); - error = EINVAL; - goto done; -found: - 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); + mtx_unlock(&Giant); + return (error); +} + +static int +swapoff_one(struct swdevt *sp, struct thread *td) +{ + u_long nblks, dvbase; #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); + int error; +#endif + + mtx_assert(&Giant, MA_OWNED); +#ifdef MAC + (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 +2172,7 @@ found: */ if (cnt.v_free_count + cnt.v_cache_count + swap_pager_avail < nblks + nswap_lowat) { - error = ENOMEM; - goto done; + return (ENOMEM); } /* @@ -2191,13 +2205,42 @@ found: mtx_unlock(&sw_dev_mtx); blist_destroy(sp->sw_blist); free(sp, M_VMPGDATA); + return (0); +} -done: +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); -done2: mtx_unlock(&Giant); - return (error); } void diff --git a/sys/vm/swap_pager.h b/sys/vm/swap_pager.h index 49a8e6f..a254cc7 100644 --- a/sys/vm/swap_pager.h +++ b/sys/vm/swap_pager.h @@ -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_ */ -- cgit v1.1