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:
Konstantin Belousov
2026-01-04 02:19:36 +02:00
parent 7361727d45
commit de77068123
3 changed files with 16 additions and 2 deletions
+8 -2
View File
@@ -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
+1
View File
@@ -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);
+7
View File
@@ -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);
}