Page MenuHomeFreeBSD

D30220.diff
No OneTemporary

D30220.diff

diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -313,8 +313,13 @@
("fork_norfproc called with RFPROC set"));
p1 = td->td_proc;
- if (((p1->p_flag & (P_HADTHREADS|P_SYSTEM)) == P_HADTHREADS) &&
- (flags & (RFCFDG | RFFDG))) {
+ /*
+ * Quiesce other threads if necessary. If RFMEM is not specified we
+ * must ensure that other threads do not concurrently create a second
+ * process sharing the vmspace, see vmspace_unshare().
+ */
+ if ((p1->p_flag & (P_HADTHREADS | P_SYSTEM)) == P_HADTHREADS &&
+ ((flags & (RFCFDG | RFFDG)) != 0 || (flags & RFMEM) == 0)) {
PROC_LOCK(p1);
if (thread_single(p1, SINGLE_BOUNDARY)) {
PROC_UNLOCK(p1);
@@ -350,8 +355,8 @@
}
fail:
- if (((p1->p_flag & (P_HADTHREADS|P_SYSTEM)) == P_HADTHREADS) &&
- (flags & (RFCFDG | RFFDG))) {
+ if ((p1->p_flag & (P_HADTHREADS | P_SYSTEM)) == P_HADTHREADS &&
+ ((flags & (RFCFDG | RFFDG)) != 0 || (flags & RFMEM) == 0)) {
PROC_LOCK(p1);
thread_single_end(p1, SINGLE_BOUNDARY);
PROC_UNLOCK(p1);
diff --git a/sys/vm/vm_glue.c b/sys/vm/vm_glue.c
--- a/sys/vm/vm_glue.c
+++ b/sys/vm/vm_glue.c
@@ -553,11 +553,9 @@
* COW locally.
*/
if ((flags & RFMEM) == 0) {
- if (refcount_load(&p1->p_vmspace->vm_refcnt) > 1) {
- error = vmspace_unshare(p1);
- if (error)
- return (error);
- }
+ error = vmspace_unshare(p1);
+ if (error)
+ return (error);
}
cpu_fork(td, p2, td2, flags);
return (0);
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -4867,6 +4867,10 @@
struct vmspace *newvmspace;
vm_ooffset_t fork_charge;
+ /*
+ * The caller is responsible for ensuring that the reference count
+ * cannot concurrently transition 1 -> 2.
+ */
if (refcount_load(&oldvmspace->vm_refcnt) == 1)
return (0);
fork_charge = 0;

File Metadata

Mime Type
text/plain
Expires
Tue, Jan 14, 2:29 PM (18 h, 17 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15794625
Default Alt Text
D30220.diff (1 KB)

Event Timeline