Date: Tue, 13 Jan 2026 14:03:23 +0000 From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: de770681234d - main - rfork(2): fix swap accounting in vmspace_unshare() Message-ID: <696650ab.86f6.171ec864@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=de770681234d001a1f4cdb8121179331dc3a2def commit de770681234d001a1f4cdb8121179331dc3a2def Author: Konstantin Belousov <kib@FreeBSD.org> AuthorDate: 2026-01-04 00:19:36 +0000 Commit: Konstantin Belousov <kib@FreeBSD.org> CommitDate: 2026-01-13 14:03:14 +0000 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 --- sys/vm/swap_pager.c | 10 ++++++++-- sys/vm/vm.h | 1 + sys/vm/vm_map.c | 7 +++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c index e0bdca07ff0f..3f077289ac30 100644 --- a/sys/vm/swap_pager.c +++ b/sys/vm/swap_pager.c @@ -330,7 +330,7 @@ out_error: } 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 diff --git a/sys/vm/vm.h b/sys/vm/vm.h index d28c84dd1c95..0da1891dfcc7 100644 --- a/sys/vm/vm.h +++ b/sys/vm/vm.h @@ -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); diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c index 68dcadd2b2f1..4c33b786eaa0 100644 --- a/sys/vm/vm_map.c +++ b/sys/vm/vm_map.c @@ -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); }home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?696650ab.86f6.171ec864>
