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
This commit is contained in:
parent
428d65f189
commit
0909f38a3c
@ -68,6 +68,12 @@ __FBSDID("$FreeBSD$");
|
||||
#include <machine/pcb.h>
|
||||
#include <machine/smp.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_object.h>
|
||||
#include <vm/vm_page.h>
|
||||
#include <vm/vm_pager.h>
|
||||
#include <vm/swap_pager.h>
|
||||
|
||||
#include <sys/signalvar.h>
|
||||
|
||||
#ifndef PANIC_REBOOT_WAIT_TIME
|
||||
@ -384,6 +390,7 @@ boot(int howto)
|
||||
if (panicstr == 0)
|
||||
vfs_unmountall();
|
||||
}
|
||||
swapoff_all();
|
||||
DELAY(100000); /* wait for console output to finish */
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
#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);
|
||||
if (error != 0)
|
||||
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
|
||||
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)
|
||||
return (error);
|
||||
#endif
|
||||
|
||||
nblks = sp->sw_nblks;
|
||||
|
||||
/*
|
||||
@ -2157,8 +2172,7 @@ swapoff(struct thread *td, struct swapoff_args *uap)
|
||||
*/
|
||||
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 @@ swapoff(struct thread *td, struct swapoff_args *uap)
|
||||
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
|
||||
|
@ -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_ */
|
||||
|
Loading…
Reference in New Issue
Block a user