Changeset View
Changeset View
Standalone View
Standalone View
sys/vm/swap_pager.c
Show First 20 Lines • Show All 464 Lines • ▼ Show 20 Lines | |||||
static void swp_sizecheck(void); | static void swp_sizecheck(void); | ||||
static void swp_pager_async_iodone(struct buf *bp); | static void swp_pager_async_iodone(struct buf *bp); | ||||
static bool swp_pager_swblk_empty(struct swblk *sb, int start, int limit); | static bool swp_pager_swblk_empty(struct swblk *sb, int start, int limit); | ||||
static void swp_pager_free_empty_swblk(vm_object_t, struct swblk *sb); | static void swp_pager_free_empty_swblk(vm_object_t, struct swblk *sb); | ||||
static int swapongeom(struct vnode *); | static int swapongeom(struct vnode *); | ||||
static int swaponvp(struct thread *, struct vnode *, u_long); | static int swaponvp(struct thread *, struct vnode *, u_long); | ||||
static int swapoff_one(struct swdevt *sp, struct ucred *cred, | static int swapoff_one(struct swdevt *sp, struct ucred *cred, | ||||
bool ignore_check); | u_int flags); | ||||
/* | /* | ||||
* Swap bitmap functions | * Swap bitmap functions | ||||
*/ | */ | ||||
static void swp_pager_freeswapspace(daddr_t blk, daddr_t npages); | static void swp_pager_freeswapspace(daddr_t blk, daddr_t npages); | ||||
static daddr_t swp_pager_getswapspace(int *npages); | static daddr_t swp_pager_getswapspace(int *npages); | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 2,012 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
/* ARGSUSED */ | /* ARGSUSED */ | ||||
int | int | ||||
sys_swapoff(struct thread *td, struct swapoff_args *uap) | sys_swapoff(struct thread *td, struct swapoff_args *uap) | ||||
{ | { | ||||
struct vnode *vp; | struct vnode *vp; | ||||
struct nameidata nd; | struct nameidata nd; | ||||
struct swdevt *sp; | struct swdevt *sp; | ||||
int error; | struct swapoff_new_args sa; | ||||
int error, probe_byte; | |||||
error = priv_check(td, PRIV_SWAPOFF); | error = priv_check(td, PRIV_SWAPOFF); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
/* | |||||
markj: IMO it is worth explaining why we do this. | |||||
* Detect old vs. new-style swapoff(2) syscall. The first | |||||
* pointer in the mmeory pointed to by uap->name is NULL for | |||||
* the old variant. | |||||
*/ | |||||
probe_byte = fubyte(uap->name); | |||||
switch (probe_byte) { | |||||
case -1: | |||||
return (EFAULT); | |||||
case 0: | |||||
error = copyin(uap->name, &sa, sizeof(sa)); | |||||
if (error != 0) | |||||
return (error); | |||||
if ((sa.flags & ~(SWAPOFF_FORCE)) != 0) | |||||
return (EINVAL); | |||||
break; | |||||
default: | |||||
bzero(&sa, sizeof(sa)); | |||||
sa.name = uap->name; | |||||
break; | |||||
} | |||||
sx_xlock(&swdev_syscall_lock); | sx_xlock(&swdev_syscall_lock); | ||||
NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1, UIO_USERSPACE, uap->name); | NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1, UIO_USERSPACE, sa.name); | ||||
error = namei(&nd); | error = namei(&nd); | ||||
if (error) | if (error) | ||||
goto done; | goto done; | ||||
NDFREE(&nd, NDF_ONLY_PNBUF); | NDFREE(&nd, NDF_ONLY_PNBUF); | ||||
vp = nd.ni_vp; | vp = nd.ni_vp; | ||||
mtx_lock(&sw_dev_mtx); | mtx_lock(&sw_dev_mtx); | ||||
TAILQ_FOREACH(sp, &swtailq, sw_list) { | TAILQ_FOREACH(sp, &swtailq, sw_list) { | ||||
if (sp->sw_vp == vp) | if (sp->sw_vp == vp) | ||||
break; | break; | ||||
} | } | ||||
mtx_unlock(&sw_dev_mtx); | mtx_unlock(&sw_dev_mtx); | ||||
if (sp == NULL) { | if (sp == NULL) { | ||||
error = EINVAL; | error = EINVAL; | ||||
goto done; | goto done; | ||||
} | } | ||||
error = swapoff_one(sp, td->td_ucred, false); | error = swapoff_one(sp, td->td_ucred, sa.flags); | ||||
Done Inline ActionsPerhaps pass the flag through directly. markj: Perhaps pass the flag through directly. | |||||
done: | done: | ||||
sx_xunlock(&swdev_syscall_lock); | sx_xunlock(&swdev_syscall_lock); | ||||
return (error); | return (error); | ||||
} | } | ||||
static int | static int | ||||
swapoff_one(struct swdevt *sp, struct ucred *cred, bool ignore_check) | swapoff_one(struct swdevt *sp, struct ucred *cred, u_int flags) | ||||
{ | { | ||||
u_long nblks; | u_long nblks; | ||||
#ifdef MAC | #ifdef MAC | ||||
int error; | int error; | ||||
#endif | #endif | ||||
sx_assert(&swdev_syscall_lock, SA_XLOCKED); | sx_assert(&swdev_syscall_lock, SA_XLOCKED); | ||||
#ifdef MAC | #ifdef MAC | ||||
Show All 13 Lines | #endif | ||||
* The vm_free_count() part does not account e.g. for clean | * The vm_free_count() part does not account e.g. for clean | ||||
* pages that can be immediately reclaimed without paging, so | * pages that can be immediately reclaimed without paging, so | ||||
* this is a very rough estimation. | * this is a very rough estimation. | ||||
* | * | ||||
* On the other hand, not turning swap off on swapoff_all() | * On the other hand, not turning swap off on swapoff_all() | ||||
* means that we can lose swap data when filesystems go away, | * means that we can lose swap data when filesystems go away, | ||||
* which is arguably worse. | * which is arguably worse. | ||||
*/ | */ | ||||
if (!ignore_check && | if ((flags & SWAPOFF_FORCE) == 0 && | ||||
vm_free_count() + swap_pager_avail < nblks + nswap_lowat) | vm_free_count() + swap_pager_avail < nblks + nswap_lowat) | ||||
return (ENOMEM); | return (ENOMEM); | ||||
/* | /* | ||||
* Prevent further allocations on this device. | * Prevent further allocations on this device. | ||||
*/ | */ | ||||
mtx_lock(&sw_dev_mtx); | mtx_lock(&sw_dev_mtx); | ||||
sp->sw_flags |= SW_CLOSING; | sp->sw_flags |= SW_CLOSING; | ||||
Show All 34 Lines | swapoff_all(void) | ||||
mtx_lock(&sw_dev_mtx); | mtx_lock(&sw_dev_mtx); | ||||
TAILQ_FOREACH_SAFE(sp, &swtailq, sw_list, spt) { | TAILQ_FOREACH_SAFE(sp, &swtailq, sw_list, spt) { | ||||
mtx_unlock(&sw_dev_mtx); | mtx_unlock(&sw_dev_mtx); | ||||
if (vn_isdisk(sp->sw_vp)) | if (vn_isdisk(sp->sw_vp)) | ||||
devname = devtoname(sp->sw_vp->v_rdev); | devname = devtoname(sp->sw_vp->v_rdev); | ||||
else | else | ||||
devname = "[file]"; | devname = "[file]"; | ||||
error = swapoff_one(sp, thread0.td_ucred, true); | error = swapoff_one(sp, thread0.td_ucred, SWAPOFF_FORCE); | ||||
if (error != 0) { | if (error != 0) { | ||||
printf("Cannot remove swap device %s (error=%d), " | printf("Cannot remove swap device %s (error=%d), " | ||||
"skipping.\n", devname, error); | "skipping.\n", devname, error); | ||||
} else if (bootverbose) { | } else if (bootverbose) { | ||||
printf("Swap device %s removed.\n", devname); | printf("Swap device %s removed.\n", devname); | ||||
} | } | ||||
mtx_lock(&sw_dev_mtx); | mtx_lock(&sw_dev_mtx); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 547 Lines • Show Last 20 Lines |
IMO it is worth explaining why we do this.