rfork(2): fix swap accounting in vmspace_unshare()
When an attempt to increase the swap charge for the ucred failed, we must forcibly increase the charge to allow the vmspace_destroy() operation to correctly un-charge the accumulated objects. Add a swap_reserve_force_by_cred() helper and use it in vmspace_unshare(), same as it is done in normal fork operations. Reviewed by: markj Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D54572
This commit is contained in:
+8
-2
@@ -330,7 +330,7 @@ swap_reserve_by_cred(vm_ooffset_t incr, struct ucred *cred)
|
||||
}
|
||||
|
||||
void
|
||||
swap_reserve_force(vm_ooffset_t incr)
|
||||
swap_reserve_force_by_cred(vm_ooffset_t incr, struct ucred *cred)
|
||||
{
|
||||
u_long pincr;
|
||||
|
||||
@@ -346,7 +346,13 @@ swap_reserve_force(vm_ooffset_t incr)
|
||||
#endif
|
||||
pincr = atop(incr);
|
||||
atomic_add_long(&swap_reserved, pincr);
|
||||
swap_reserve_force_rlimit(pincr, curthread->td_ucred);
|
||||
swap_reserve_force_rlimit(pincr, cred);
|
||||
}
|
||||
|
||||
void
|
||||
swap_reserve_force(vm_ooffset_t incr)
|
||||
{
|
||||
swap_reserve_force_by_cred(incr, curthread->td_ucred);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -168,6 +168,7 @@ void vm_ksubmap_init(struct kva_md_info *);
|
||||
bool swap_reserve(vm_ooffset_t incr);
|
||||
bool swap_reserve_by_cred(vm_ooffset_t incr, struct ucred *cred);
|
||||
void swap_reserve_force(vm_ooffset_t incr);
|
||||
void swap_reserve_force_by_cred(vm_ooffset_t incr, struct ucred *cred);
|
||||
void swap_release(vm_ooffset_t decr);
|
||||
void swap_release_by_cred(vm_ooffset_t decr, struct ucred *cred);
|
||||
|
||||
|
||||
@@ -4957,6 +4957,13 @@ vmspace_unshare(struct proc *p)
|
||||
if (newvmspace == NULL)
|
||||
return (ENOMEM);
|
||||
if (!swap_reserve_by_cred(fork_charge, p->p_ucred)) {
|
||||
/*
|
||||
* The swap reservation failed. The accounting from
|
||||
* the entries of the copied newvmspace will be
|
||||
* subtracted in vmspace_free(), so force the
|
||||
* reservation there.
|
||||
*/
|
||||
swap_reserve_force_by_cred(fork_charge, p->p_ucred);
|
||||
vmspace_free(newvmspace);
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user