[SSI] openssi/kernel/cluster/ssi/vproc as_xscribe.c, 1.17, 1.18 dvp_async.c, 1.11, 1.12 dvp_init.c, 1.16, 1.17 dvp_lock.c, 1.6, 1.7 dvp_misc.c, 1.16, 1.17 dvp_move.c, 1.14, 1.15 dvp_pvpops.c, 1.40, 1.41 dvp_pvpsops.c, 1.18, 1.19 dvp_vpops.c, 1.40, 1.41 nd_carelist.c, 1.8, 1.9 nd_cleanup.c, 1.9, 1.10 nd_object.c, 1.6, 1.7 nd_origin.c, 1.11, 1.12 nd_setup.c, 1.10, 1.11 nd_slave.c, 1.11, 1.12 nsc_initproc.c, 1.23, 1.24 pproc_subr.c, 1.11, 1.12 procfs_mount.c, 1.12, 1.13 procfs_subr.c, 1.15, 1.16 reopen.c, 1.32, 1.33 rproc_cli_pproc.c, 1.22, 1.23 rproc_cli_vproc.c, 1.10, 1.11 rproc_server.c, 1.9, 1.10 rproc_server_pproc.c, 1.13, 1.14 rproc_svr_pproc.c, 1.25, 1.26 rproc_svr_vproc.c, 1.16, 1.17 vp_debug.c, 1.14, 1.15 vp_init.c, 1.8, 1.9 vp_subr.c, 1.20, 1.21

Roger Tsang <[email protected]>
Newsgroups gmane.linux.cluster.ssic.cvs
Message-ID <[email protected]>
Update of /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/vproc
In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvs-serv16224/kernel/cluster/ssi/vproc

Modified Files:
      Tag: OPENSSI-FC
	as_xscribe.c dvp_async.c dvp_init.c dvp_lock.c dvp_misc.c 
	dvp_move.c dvp_pvpops.c dvp_pvpsops.c dvp_vpops.c 
	nd_carelist.c nd_cleanup.c nd_object.c nd_origin.c nd_setup.c 
	nd_slave.c nsc_initproc.c pproc_subr.c procfs_mount.c 
	procfs_subr.c reopen.c rproc_cli_pproc.c rproc_cli_vproc.c 
	rproc_server.c rproc_server_pproc.c rproc_svr_pproc.c 
	rproc_svr_vproc.c vp_debug.c vp_init.c vp_subr.c 
Log Message:
Bug fixes and enhancements. See ChangeLog.


Index: vp_subr.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/vproc/vp_subr.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- vp_subr.c	24 Mar 2009 04:26:28 -0000	1.20
+++ vp_subr.c	27 Oct 2009 03:18:30 -0000	1.21
@@ -49,15 +49,15 @@
 #ifdef VPROC_RELEASE__REFCNT_RACE_FIX
 			/* [ ssic-linux-Bugs-1842982 ] vproc dealloc'ed */
 			if (hold)
+				v = __vproc_hold_and_check(v);
 #endif
-			if (!VPROC_HOLD_AND_CHECK(v, "vprocptr"))
-				v = NULL;
-			rcu_read_unlock();
-			return v;
+			goto out;
 		}
 	}
+	v = NULL;
+out:
 	rcu_read_unlock();
-	return NULL;
+	return v;
 #else /* !VPROC_RCU_LIST */
 	int found = 0;
 
@@ -116,7 +116,11 @@
 #ifdef VPROC_RCU_LIST
 		INIT_RCU_HEAD(&v->vp_rcu);
 #endif
+#ifdef ATOMIC_VPROC_REFCNT
+		INIT_SPIN_LOCK(&v->vp_lock);
+#else
 		VPROC_REFCNT_LOCK_INIT(v);
+#endif
 
 		VPROC_LOCK_INIT(v);
 		VPROC_LOCK_ND_LIST_INIT(v);
@@ -135,7 +139,7 @@
 {
 	size_t size = sizeof(struct vproc) + sizeof(struct pvproc);
 
-	vproc_cachep = kmem_cache_create("vproc_cache",
+	vproc_cachep = kmem_cache_create("ssi_vproc",
 				size, 0,
 				SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|SLAB_PANIC,
 				vproc_ctor, NULL);
@@ -167,12 +171,20 @@
 	v->vp_next = NULL;
 #endif
 #if __SSI_LOCK_DEBUG
+#ifdef ATOMIC_VPROC_REFCNT
+	INIT_SPIN_LOCK(&v->vp_lock);
+#else
 	VPROC_REFCNT_LOCK_INIT(v);
 #endif
+#endif
 #else
 	v = kzmalloc_nofail(size);
 	v->vp_data = ((char *)v) + sizeof(struct vproc);
+#ifdef ATOMIC_VPROC_REFCNT
+	INIT_SPIN_LOCK(&v->vp_lock);
+#else
 	VPROC_REFCNT_LOCK_INIT(v);
+#endif
 #endif /* !VPROC_KMEM_CACHE */
 
 #ifdef VPROC_RELEASE__REFCNT_RACE_FIX
@@ -180,7 +192,7 @@
 #ifndef ATOMIC_VPROC_REFCNT
 	v->vp_ref_cnt = 1;
 #else
-	INIT_ATOMIC_INT(&v->vp_ref_cnt, 1);
+	atomic_set(&v->vp_ref_cnt, 1);
 #endif
 #else /* !VPROC_RELEASE__REFCNT_RACE_FIX */
 #ifndef ATOMIC_VPROC_REFCNT
@@ -196,6 +208,9 @@
 	INIT_LIST_HEAD(&v->vp_carelist);
 #endif
 	v->vp_magic = VP_MAGIC;
+#ifdef TASK_HOLD_VPROC
+	v->vp_relse = 0;
+#endif
 
 #ifdef VPROC_DEBUG
 	nvproc++;
@@ -231,7 +246,11 @@
 #ifdef VPROC_KMEM_CACHE
 	kmem_cache_free(vproc_cachep, vp);
 #else
+#ifdef ATOMIC_VPROC_REFCNT
+	DEINIT_SPIN_LOCK(&vp->vp_lock);
+#else
 	VPROC_REFCNT_LOCK_DEINIT(vp);
+#endif
 	kfree(vp);
 #endif
 #ifdef VPROC_DEBUG
@@ -239,6 +258,56 @@
 #endif
 }
 
+#ifdef TASK_HOLD_VPROC
+/* Called during final put_task_struct() */
+void release_vproc(struct task_struct *p)
+{
+	struct vproc *v = p->p_vproc;
+
+	if (!v)
+		return;
+	p->p_vproc = NULL;
+
+	/* Delay dealloc till final vproc_release() */
+	if (xchg(&v->vp_relse, VP_DEAD) == VP_GIVEBACK)
+		free_vproc(v);
+}
+#endif /* TASK_HOLD_VPROC */
+
+#ifndef VPROC_HOLD_ZERO_GET_TASK
+#define vproc_giveback(_v) free_vproc(_v)
+#else
+static void
+vproc_giveback(struct vproc *v)
+{
+	task_t *tsk = PVP(v)->pvp_pproc;
+
+#ifndef TASK_HOLD_VPROC
+	if (tsk) {
+		WARN_ON(PV_IS_ALIVE(PVP(v)));
+		PVP(v)->pvp_pproc = NULL;
+		put_task_struct(tsk);
+	}
+	free_vproc(v);
+#else
+	if (!tsk) {
+		free_vproc(v);
+		return;
+	}
+	BUG_ON(PV_IS_ALIVE(PVP(v)));
+
+	if (PVP(v)->pvp_flag & PV_PROCESS) {
+		PVP(v)->pvp_flag &= ~PV_PROCESS;
+		PVP(v)->pvp_pproc = NULL;
+		put_task_struct(tsk);
+	} /* else pvp_pproc is released early due to migration */
+
+	/* Delay dealloc till final put_task_struct() */
+	if (xchg(&v->vp_relse, VP_GIVEBACK) == VP_DEAD)
+		free_vproc(v);
+#endif /* TASK_HOLD_VPROC */
+}
+#endif /* VPROC_HOLD_ZERO_GET_TASK */
 
 /*
  * Release a hold on a vproc and free it if
@@ -265,7 +334,7 @@
 	int locked = 0;		/* tncvpd_scan() has lock ? */
 #endif
 
-	BUG_ON(!VPROCPTR_VALID(v));
+	BUG_ON(!VP_HASHED(v));
 #ifndef ATOMIC_VPROC_REFCNT
 	SSI_ASSERT(v->vp_ref_cnt != 0);
 
@@ -287,13 +356,15 @@
 		VPROC_REFCNT_UNLOCK(v);
 	}
 #else
-	might_sleep_if(atomic_read(&v->vp_ref_cnt) == 1);
 #ifdef VPROC_LIST_SPINLOCK
-	if (!atomic_dec_and_lock(&v->vp_ref_cnt, &vproc_list_lock))
+	if (!atomic_dec_and_lock(&v->vp_ref_cnt, &vproc_list_lock)) {
+		/* WARN_ON(atomic_read(&v->vp_ref_cnt) < 0); */
+		return(ESUCCESS);
+	}
 #else
 	if (!atomic_dec_and_test(&v->vp_ref_cnt))
-#endif
 		return(ESUCCESS);
+#endif
 #endif /* ATOMIC_VPROC_REFCNT */
 
 #ifndef VPROC_HASH_LIST
@@ -314,24 +385,24 @@
 
 #ifdef VPROC_RELEASE__REFCNT_RACE_FIX
 #ifdef VPROC_LIST_SPINLOCK
-	BUG_ON(!VPROCPTR_VALID(v));
+	BUG_ON(!VP_HASHED(v));
 #else
 	/* [ ssic-linux-Bugs-1842982 ]
 	 * vproc dealloc'ed before we got list lock.
 	 */
-	if (!VPROCPTR_VALID(v))
+	if (!VP_HASHED(v))
 		goto out_unlock;
 #endif
 #endif /* VPROC_RELEASE__REFCNT_RACE_FIX */
 
 #ifdef ATOMIC_VPROC_REFCNT
-	VPROC_REFCNT_LOCK(v);
-	if (READ_ATOMIC_INT(&v->vp_ref_cnt)) {
-		VPROC_REFCNT_UNLOCK(v);
+	LOCK_SPIN_LOCK(&v->vp_lock);
+	if (atomic_read(&v->vp_ref_cnt)) {
+		UNLOCK_SPIN_LOCK(&v->vp_lock);
 		goto out_unlock;
 	}
 	v->vp_magic = 0;
-	VPROC_REFCNT_UNLOCK(v);
+	UNLOCK_SPIN_LOCK(&v->vp_lock);
 #else
 	/*
 	 * Reference count got bumped; just
@@ -380,66 +451,75 @@
 	/*
 	 * Give back vproc storage
 	 */
-	if (giveback) {
-#ifdef VPROC_HOLD_ZERO_GET_TASK
-		if (PVP(v)->pvp_pproc) {
-			WARN_ON(PV_IS_ALIVE(PVP(v)));
-			put_task_struct(PVP(v)->pvp_pproc);
-			PVP(v)->pvp_pproc = NULL;
-		}
-#endif
-#ifdef VPROC_RCU_LIST
-		call_rcu(&v->vp_rcu, vproc_dealloc);
-#else
-		vproc_dealloc(v);
-#endif
-	}
+	if (giveback)
+		vproc_giveback(v);
 
 	return(ESUCCESS);
 }
 
 #ifdef VPROC_RELEASE__REFCNT_RACE_FIX
+#ifndef ATOMIC_VPROC_REFCNT
+#error not supported
+#endif
 struct vproc *
-#else
-int
+__vproc_hold_and_check(struct vproc *v)
+{
+	LOCK_SPIN_LOCK(&v->vp_lock);
+	if (!VP_HASHED(v)) {
+		/* Lost the race */
+		UNLOCK_SPIN_LOCK(&v->vp_lock);
+		return NULL;
+	}
+	atomic_inc(&v->vp_ref_cnt);
+	UNLOCK_SPIN_LOCK(&v->vp_lock);
+#ifdef NSCVPD_DEBUG
+	PVP(v)->pvp_lasthold = TICKS();
 #endif
-vproc_hold(
-	struct vproc *v,
-	int check)
+	return v;
+}
+
+struct vproc *
+vproc_hold_and_check(struct vproc *v)
 {
-#ifdef VPROC_RELEASE__REFCNT_RACE_FIX
-	if (check) {
-		VPROC_REFCNT_LOCK(v);
-		if (!VPROCPTR_VALID(v)) {
-			/* Lost the race */
-			VPROC_REFCNT_UNLOCK(v);
-			return NULL;
-		}
-#ifdef ATOMIC_VPROC_REFCNT
-		INCR_ATOMIC_INT(&v->vp_ref_cnt);
-#else
-		v->vp_ref_cnt++;
+	struct vproc *vp = NULL;
+
+#ifdef TASK_HOLD_VPROC
+	if (!v) /* Raced with process creation */
+		return NULL;
 #endif
-		VPROC_REFCNT_UNLOCK(v);
-		return v;
-	}
+#ifdef VPROC_RCU_LIST
+	rcu_read_lock(); /* Prevent bogus vp_lock */
+#ifdef TASK_HOLD_VPROC
+	if (!VP_HASHED(v))
+		goto out;
+#endif
+#endif /* VPROC_RCU_LIST */
+	vp = __vproc_hold_and_check(v);
+#ifdef VPROC_RCU_LIST
+#ifdef TASK_HOLD_VPROC
+out:
+#endif
+	rcu_read_unlock();
+#endif
+	return vp;
+}
 #endif /* VPROC_RELEASE__REFCNT_RACE_FIX */
-	BUG_ON(!VPROCPTR_VALID(v));
+
+int
+vproc_hold(struct vproc *v)
+{
+	BUG_ON(!VP_HASHED(v));
 #ifndef ATOMIC_VPROC_REFCNT
 	VPROC_REFCNT_LOCK(v);
 	v->vp_ref_cnt++;
 	VPROC_REFCNT_UNLOCK(v);
 #else
-	INCR_ATOMIC_INT(&v->vp_ref_cnt);
+	atomic_inc(&v->vp_ref_cnt);
 #endif
 #ifdef NSCVPD_DEBUG
 	PVP(v)->pvp_lasthold = TICKS();
 #endif
-#ifdef VPROC_RELEASE__REFCNT_RACE_FIX
-	return v;
-#else
 	return(ESUCCESS);
-#endif
 }
 
 pid_t ssi_get_ppid(pid_t pid)
@@ -455,18 +535,35 @@
 	return ppid;
 }
 
+/* Called under tasklist_lock for thread group */
 struct task_struct *ssi_get_ppid_task(struct task_struct *t)
 {
 	struct vproc *vp;
 
-	if (t) {
-		vp = VPROCPTR(t->ppid);
+	if (!t)
+		return NULL;
+
+	vp = VPROCPTR(t->ppid);
+#ifdef TASK_HOLD_VPROC
+	if (vp) {
+		/* We can skip VPROC_HOLD_MOVEMENT() and get_task_struct()
+		 * since entire thread group migrates.
+		 */
+		task_t *p = PVP(vp)->pvp_pproc;
+
+		/* SSI_ASSERT(PV_IS_ALIVE(PVP(vp))); */
+
 #ifdef VPROC_RELEASE__REFCNT_RACE_FIX
-		/* Caller responsible for releasing vproc ptr */
-		/* SSI_XXX TODO: zap_threads() to release vp */
+		VPROC_RELE(vp, "ssi_get_ppid_task");
 #endif
-		return (vp ? PVP(vp)->pvp_pproc : NULL);
+		return p;
 	}
-
 	return NULL;
+#else
+#ifdef VPROC_RELEASE__REFCNT_RACE_FIX
+	/* Caller responsible for releasing vproc ptr */
+	/* SSI_XXX TODO: zap_threads() to release vp */
+#endif
+	return (vp ? PVP(vp)->pvp_pproc : NULL);
+#endif /* !TASK_HOLD_VPROC */
 }

Index: dvp_async.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/vproc/dvp_async.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- dvp_async.c	3 Feb 2009 06:18:13 -0000	1.11
+++ dvp_async.c	27 Oct 2009 03:18:29 -0000	1.12
@@ -109,7 +109,6 @@
 	if (cr != NULL)
 		get_rpccred(cr);
 	sigproc_data->cr = cr;
-
 	error = nsc_async_queue(nsc_generic_async_queue,
 				dpvproc_sigproc_async_handler,
 				sigproc_data,
@@ -224,7 +223,6 @@
 	if (cr != NULL)
 		get_rpccred(cr);
 	sigpgrp_data->cr = cr;
-
 	error = nsc_async_queue(nsc_generic_async_queue,
 				dpvproc_sigpgrp_async_handler,
 				sigpgrp_data,
@@ -295,6 +293,7 @@
 	vc = nocldwait_datap->vc;
 
 #ifdef RELEASE_TASK_LEADER_GONE__VPROC_FIX
+	SSI_ASSERT(vp);
 	if (!vp)
 		goto release_child;
 #endif
@@ -330,10 +329,16 @@
 #endif
 			goto out;
 		}
+#ifdef RELEASE_TASK_LEADER_GONE__VPROC_FIX
+		VPROC_RELEASE_MOVEMENT(vp, "dpvproc_nocldwait_async_handler");
+#endif
 		VPROC_RELE(vp, "temp nocldwait async (parent)");
 		vp = LOCATE_VPROC_PID(PVP(vc)->pvp_ppid,
 				      "temp nocldwait async (new parent)");
 		SSI_ASSERT(vp != NULL);
+#ifdef RELEASE_TASK_LEADER_GONE__VPROC_FIX
+		VPROC_HOLD_MOVEMENT(vp, "temp nocldwait async (new parent)");
+#endif
 		error = PVPOP_RMV_CHILD_FROM_PARENT(vp, vc, FALSE);
 		if (error != 0) {
 #ifdef VPROC_DEBUG
@@ -456,12 +461,14 @@
 #ifdef NSC_ASYNC_ARGS_ZERO_COPY
 	nocldwait_data->vp = vp;
 	nocldwait_data->vc = vc;
-
 	error = nsc_async_queue(nsc_async_nocldwait_queue,
 				dpvproc_nocldwait_async_handler,
 				nocldwait_data,
 				sizeof(*nocldwait_data),
 				NSC_ASYNC_SLEEP | NSC_ASYNC_ARGS_FREE);
+	if (error)
+		printk(KERN_WARNING "%s: unable to allocate async event; error=%d\n",
+				__FUNCTION__, error);
 #else
 	nocldwait_data.vp = vp;
 	nocldwait_data.vc = vc;
@@ -479,6 +486,7 @@
 
 	/* Wakeup pid 2 to cleanup */
 	vp = VPROCPTR(2);
+	SSI_ASSERT(vp);
 	send_sig_info(SIGCHLD, (void *)1, PVP(vp)->pvp_pproc);
 #ifdef VPROC_RELEASE__REFCNT_RACE_FIX
 	VPROC_RELE(vp, "dpvproc_nocldwait_async_queue(vprocptr vp)");
@@ -540,7 +548,6 @@
 	rmv_data->vg = vg;
 	rmv_data->vc = vc;
 	rmv_data->ppid = ppid;
-
 	error = nsc_async_queue(nsc_generic_async_queue,
 				dpvproc_rmv_pgrp_async_handler,
 				rmv_data,
@@ -567,6 +574,6 @@
 				NSC_ASYNC_DUPCHECK);
 #endif /* !NSC_ASYNC_ARGS_ZERO_COPY */
 	if (error)
-		printk(KERN_WARNING "%s: unable to allocate async event; error=%d",
+		printk(KERN_WARNING "%s: unable to allocate async event; error=%d\n",
 				__FUNCTION__, error);
 }

Index: dvp_misc.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/vproc/dvp_misc.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- dvp_misc.c	24 Mar 2009 04:26:28 -0000	1.16
+++ dvp_misc.c	27 Oct 2009 03:18:29 -0000	1.17
@@ -36,6 +36,9 @@
 #include <cluster/ics.h>
 #include <cluster/ssi/rcopy.h>
 #include <cluster/ssi/mosixll/defs.h>
+#ifdef SSI_BALANCE_MEMORY
+#include <cluster/ssi/mosixll/balance.h>
+#endif
 
 #include <cluster/gen/rproc.h>
 
@@ -119,6 +122,7 @@
 				error = retval;
 		}
 	}
+	NSC_NODELIST_FREE(nlist);
  out:
 	/* Reacquire tasklist_lock because will be trying to unlock */
 	read_lock(&tasklist_lock);
@@ -171,6 +175,7 @@
 		} else if (retval > niceval)
 			niceval = retval;
 	}
+	NSC_NODELIST_FREE(nlist);
  out:
 	/* Reacquire tasklist_lock because will be trying to unlock */
 	read_lock(&tasklist_lock);
@@ -246,6 +251,8 @@
 		PVPSOP_CAPABILITY_UNLOCK_NODE(node, NSC_MY_PID, 1);
 	}
 
+	NSC_NODELIST_FREE(nlist);
+
 	return error;
 }
 
@@ -352,6 +359,7 @@
 			if (retval < error)
 				error = retval;
 		}
+	NSC_NODELIST_FREE(nlist);
 
 	return error;
 }
@@ -367,16 +375,17 @@
 {	
 	struct dentry *de;
 	struct vfsmount *mnt;
+	task_t *p = current;
+	struct vproc *vp = p->p_vproc;
 
-	write_lock_irq(&tasklist_lock);
-	de = PVP(current->p_vproc)->pvp_comm_de;
-	mnt = PVP(current->p_vproc)->pvp_comm_mnt;
-	mb();
+	task_lock(p);
 
+	de = PVP(vp)->pvp_comm_de;
+	mnt = PVP(vp)->pvp_comm_mnt;
 	/* set the dentry and mnt ptrs for the executable name */
-	PVP(current->p_vproc)->pvp_comm_de = dget(f->f_dentry);
-	PVP(current->p_vproc)->pvp_comm_mnt = mntget(f->f_vfsmnt);
-	write_unlock_irq(&tasklist_lock);
+	PVP(vp)->pvp_comm_de = dget(f->f_dentry);
+	PVP(vp)->pvp_comm_mnt = mntget(f->f_vfsmnt);
+	task_unlock(p);
 
 	dput(de);
 	mntput(mnt);
@@ -387,35 +396,34 @@
 {
 	struct dentry *de;
 	struct vfsmount *mnt;
+	task_t *p = current;
+	struct vproc *vp = p->p_vproc;
 
-	write_lock_irq(&tasklist_lock);
+	(void)f;
 
-	/* release and clear the ptrs for the executable name */
-	if (f) {
-		de = f->f_dentry;
-		mnt = f->f_vfsmnt;
-	} else {
-		de = PVP(current->p_vproc)->pvp_comm_de;
-		mnt = PVP(current->p_vproc)->pvp_comm_mnt;
-		mb();
-	}
+	if (!vp)
+		return;
 
-	PVP(current->p_vproc)->pvp_comm_de = NULL;
-	PVP(current->p_vproc)->pvp_comm_mnt = NULL;
-	write_unlock_irq(&tasklist_lock);
+	task_lock(p);
+
+	de = PVP(vp)->pvp_comm_de;
+	mnt = PVP(vp)->pvp_comm_mnt;
+	/* release and clear the ptrs for the executable name */
+	PVP(vp)->pvp_comm_de = NULL;
+	PVP(vp)->pvp_comm_mnt = NULL;
+	task_unlock(p);
 
 	dput(de);
 	mntput(mnt);
 }
 
 int
+#ifdef VPROC_HOLD_ZERO_GET_TASK
+__deprecated
+#endif
 ssi_vproc_destroy(struct task_struct *task)
 {
-#ifdef VPROC_HOLD_ZERO_GET_TASK
-	if (task->p_vproc && PV_IS_ALIVE(PVP(task->p_vproc)))
-#else
 	if (task->p_vproc && PVP(task->p_vproc)->pvp_pproc != NULL)
-#endif
 		return 0;
 	return 1;
 }
@@ -428,18 +436,28 @@
 	int ind = 0;
 	int i;
 	struct vproc *v = NULL;
-	struct vproc **vp_list;
+	struct vproc **vproc_list;
 
 	/* turn loadleveling off for this node */
-	loadlevel_on = 0;
+	atomic_set(&loadlevel_on, 0);
+#ifdef SSI_BALANCE_MEMORY
+	while (latest_free_mem || loadinfo[0].mem) {
+		/* write_lock(&loadinfo_lock); */
+		loadinfo[0].mem = 0;
+		/* write_unlock(&loadinfo_lock); */
+		set_mb(latest_free_mem, 0);
+		idelay(HZ/10); /* Re-check for race with compute_freemem() */
+	}
+#else
 	latest_free_mem = 0;
 	loadinfo[0].mem = 0;
+#endif
 
 #ifndef VPROC_IS_LOADLEVELABLE
 #ifdef VPROC_HOLD_ZERO_GET_TASK
 #define VPROC_IS_LOADLEVELABLE(_v) \
-	(PVP(_v)->pvp_loadlevel && \
-	 PV_IS_ALIVE(PVP(_v)) && \
+	(PVP(_v)->pvp_loadlevel == 1 && \
+	 (PVP(_v)->pvp_flag & PV_IS_LOCAL) && \
 	 VPROCNODE(_v->vp_pid) != this_node)
 #else
 #define VPROC_IS_LOADLEVELABLE(_v) \
@@ -449,12 +467,12 @@
 #endif /* !VPROC_HOLD_ZERO_GET_TASK */
 #endif
 
+	for (i=0; i < vprochsz; i++) {
 #ifdef VPROC_RCU_LIST
-	rcu_read_lock();
+		rcu_read_lock();
 #else
-	VPROC_LIST_LOCK();      
+		VPROC_LIST_LOCK();
 #endif
-	for (i=0; i < vprochsz; i++) {
 #ifdef VPROC_HASH_LIST
 #ifdef VPROC_RCU_LIST
 		list_for_each_entry_rcu(v, &vproc_hash[i], vp_list) {
@@ -468,25 +486,27 @@
 			if (VPROC_IS_LOADLEVELABLE(v))
 				count++;
 		}       
-	}
 #ifdef VPROC_RCU_LIST
-	rcu_read_unlock();
+		rcu_read_unlock();
 #else
-	VPROC_LIST_UNLOCK();
+		VPROC_LIST_UNLOCK();
 #endif
+	}
 
-	vp_list = kzmalloc(count * sizeof(struct vproc *), GFP_KERNEL);
-	if (!vp_list) {
+	if (count == 0)
+		return;
+	vproc_list = kmalloc(count * sizeof(struct vproc *), GFP_KERNEL);
+	if (!vproc_list) {
 		printk("%s:Failed to allocate memory\n", __FUNCTION__);
 		return;
 	}
 
+	for (i=0; i < vprochsz; i++) {
 #ifdef VPROC_RCU_LIST
-	rcu_read_lock();
+		rcu_read_lock();
 #else
-	VPROC_LIST_LOCK();      
+		VPROC_LIST_LOCK();
 #endif
-	for (i=0; i < vprochsz; i++) {
 #ifdef VPROC_HASH_LIST
 #ifdef VPROC_RCU_LIST
 		list_for_each_entry_rcu(v, &vproc_hash[i], vp_list) {
@@ -497,36 +517,37 @@
 		for (v = vproc_hash[i]; v != 0; v = v->vp_hashfwd) {
 			prefetch(v->vp_hashfwd);
 #endif
-			if (VPROC_IS_LOADLEVELABLE(v)) {
-				if (ind >= count)
-					break;
-#ifdef VPROC_RELEASE__REFCNT_RACE_FIX
-				if (VPROC_HOLD_AND_CHECK(v, "move_eligible_processes_off"))
-					vp_list[ind++] = v;
+#ifdef VPROC_RCU_LIST
+			if (VPROC_IS_LOADLEVELABLE(v) && __vproc_hold_and_check(v)) {
 #else
-				vp_list[ind++] = v;
+			if (VPROC_IS_LOADLEVELABLE(v)) {
 				VPROC_HOLD(v, "move_eligible_processes_off");
 #endif
+				vproc_list[ind++] = v;
+				if (ind == count)
+					break;
 			}
 		}       
-		if (ind >= count)
-			break;
-	}
 #ifdef VPROC_RCU_LIST
-	rcu_read_unlock();
+		rcu_read_unlock();
 #else
-	VPROC_LIST_UNLOCK();
+		VPROC_LIST_UNLOCK();
 #endif
+		if (ind == count)
+			break;
+	}
 
-	for(i = 0; i < count; i++) {
-		v = vp_list[i];
-#ifdef VPROC_RCU_LIST
-		if (!v)
-			continue;
-#endif
+	for(i = 0; i < ind; i++) {
+		v = vproc_list[i];
+#ifdef TASK_HOLD_VPROC
+		(void) vproc_migrate_local(v, CLUSTERNODE_BEST);
+#else
 		if (PVP(v)->pvp_pproc && !(PVP(v)->pvp_flag & PV_EXITING))
 			proc_migrate(PVP(v)->pvp_pproc, CLUSTERNODE_BEST);
+#endif
 		VPROC_RELE(v, "move_eligible_processes_off");
 	}
+
+	kfree(vproc_list);
 }
 #endif

Index: nsc_initproc.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/vproc/nsc_initproc.c,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -d -r1.23 -r1.24
--- nsc_initproc.c	24 Mar 2009 04:26:28 -0000	1.23
+++ nsc_initproc.c	27 Oct 2009 03:18:30 -0000	1.24
@@ -373,13 +373,16 @@
 		if (cvp == NULL) {
 			VPROC_LOCK_ND_LIST_EXCL(vp, "initproc_add_reclaim_children");
 			PVP(nvp)->pvp_childl = pvp->pvp_head_childl;
-			mb();
 			pvp->pvp_head_childl = nvp;
 			VPROC_UNLOCK_ND_LIST_EXCL(vp, "initproc_add_reclaim_children");
-			VPROC_HOLD(vp, "initproc_add_reclaim_children");
+			VPROC_HOLD(vp, "initproc_add_reclaim_children(parent)");
 		}
 #endif /* !VPROC_PVP_CHILD_LL */
 		VPROC_UNLOCK_EXCL(vp, "initproc_add_reclaim_children");
+#ifdef VPROC_RELEASE__REFCNT_RACE_FIX
+		if (cvp) /* if nvp was not added to sibling-child list */
+			VPROC_RELE(nvp, "initproc_add_reclaim_children");
+#endif
 	}
 }
 

Index: nd_object.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/vproc/nd_object.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- nd_object.c	3 Feb 2009 06:18:13 -0000	1.6
+++ nd_object.c	27 Oct 2009 03:18:30 -0000	1.7
@@ -154,8 +154,8 @@
 	vproc_carehead_t *vchp;
 	vproc_caredata_t *vcdp;
 	void (*func_ptr)(pid_t, void *);
-	void *args_ptr;
 
+#ifndef NSC_ASYNC_ARGS_ZERO_COPY
 	/*
 	 * Allocate a new carehead structure and copy the passed-in
 	 * carehead data into it.  This allows us to perform a
@@ -163,6 +163,19 @@
 	 */
 	vchp = vproc_carehead_alloc();
 	*vchp = *((vproc_carehead_t *)args);
+#else
+	vchp = (vproc_carehead_t *)args;
+#endif
+	/* SSI_XXX: deadlock
+	 * vproc_objhash_lock	(vproc_object_nodedown_handler)
+	 *			(dpvproc_ctty_losing_session_leader)
+	 *			(pvpsop_release_ctty)
+	 *			(pps_release_ctty)
+	 *			(vpop_setctty)
+	 * vproc_objhash_lock	(vproc_object_nodedown_dereg)
+	 */
+	/* No need lock; vproc_carehead_list_remove() already done */
+	/* LOCK_LOCK(&vproc_objhash_lock); */
 
 	/*
 	 * Invoke the registered callback routines
@@ -172,9 +185,8 @@
 	     vcdp; vcdp = vproc_caredata_get_next(vchp, vcdp)) {
 		func_ptr = (void (*)(pid_t, void *))
 			   vcdp->vcd_carer;
-		args_ptr = (void *)vcdp->vcd_data;
 
-		(*func_ptr)((pid_t)vcdp->vcd_target, args_ptr);
+		(*func_ptr)((pid_t)vcdp->vcd_target, (void *)vcdp->vcd_data);
 	}
 
 	vproc_carelist_release(vchp);
@@ -197,8 +209,10 @@
 
 	extern int process_is_alive(pid_t);
 
-	LOCK_LOCK(&vproc_objhash_lock);
 	for (i = 0; i < VPROC_OBJHASHSZ; i++) {
+
+		LOCK_LOCK(&vproc_objhash_lock);
+
 		vchp = vproc_objhash[i];
 		while (vchp) {
 			nvchp = vchp->vch_next;
@@ -215,22 +229,16 @@
 				 * Queue the carelist for callbacks to be
 				 * performed asynchronously.
 				 */
-#ifdef NSC_ASYNC_ARGS_ZERO_COPY
-				error = nsc_async_queue(
-						nsc_generic_async_queue,
-						vproc_object_nodedown_handler,
-						(void *)vchp,
-						sizeof(*vchp),
-						NSC_ASYNC_ARGS_FREE);
-#else
 				error = nsc_async_queue(
 						nsc_generic_async_queue,
 						vproc_object_nodedown_handler,
 						(void *)vchp,
 						sizeof(vproc_carehead_t),
 						0);
-#endif
 				if (error) {
+#ifdef NSC_ASYNC_ARGS_ZERO_COPY
+					vproc_carehead_dealloc(vchp);
+#endif
 					printk(KERN_WARNING
 						"vproc_object_nodedown: unable"
 						" to allocate async event;"
@@ -249,6 +257,6 @@
 
 			vchp = nvchp;
 		}
+		UNLOCK_LOCK(&vproc_objhash_lock);
 	}
-	UNLOCK_LOCK(&vproc_objhash_lock);
 }

Index: dvp_lock.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/vproc/dvp_lock.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- dvp_lock.c	10 May 2005 12:52:54 -0000	1.6
+++ dvp_lock.c	27 Oct 2009 03:18:29 -0000	1.7
@@ -109,7 +109,7 @@
 	}
 
 	if (local_only && (PVP(vp)->pvp_flag & PV_IS_LOCAL) == 0) {
-		/* Should create a clean macro for this check */
+		/* TODO: Should create a clean macro for this check */
 		if (!waitqueue_active(&(&mlp->ml_shr_cond)->cnd_wqh))
 			mlp->ml_flag &= ~ML_SHR_LOCK_HELD_OR_PENDING;
 		error = -EREMOTE;
@@ -161,8 +161,7 @@
 	while ((mlp->ml_flag & ML_EXCL_LOCK_HELD) != 0 ||
 			mlp->ml_shr_count > 0) {
 		mlp->ml_excl_count++;
-		WAIT_CONDITION_NORELCK(&mlp->ml_excl_cond, &mlp->ml_lock);
-		LOCK_COND_LOCK(&mlp->ml_lock);
+		WAIT_CONDITION(&mlp->ml_excl_cond, &mlp->ml_lock);
 		mlp->ml_excl_count--;
 		SSI_ASSERT(mlp->ml_excl_count >= 0);
 	}
@@ -170,7 +169,6 @@
 	mlp->ml_flag |= ML_EXCL_LOCK_HELD;
 
 	UNLOCK_COND_LOCK(&mlp->ml_lock);
-
 }
 
 void

Index: nd_setup.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/vproc/nd_setup.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- nd_setup.c	24 Mar 2009 04:26:28 -0000	1.10
+++ nd_setup.c	27 Oct 2009 03:18:30 -0000	1.11
@@ -164,7 +164,6 @@
 	 * Add pgrp member to pgrp leader list.
 	 */
 	PVP(vm)->pvp_pgrpl = PVP(vl)->pvp_head_pgrpl;
-	mb();
 	PVP(vl)->pvp_head_pgrpl = vm;
 }
 
@@ -197,10 +196,10 @@
 	 * Add session member to session leader list.
 	 */
 	PVP(vm)->pvp_sessionl = PVP(vl)->pvp_sessionl;
-	mb();
 	PVP(vl)->pvp_sessionl = vm;
 }
 
+/* Called with vod_carehash_rwlock held */
 void
 vproc_setup_groups(
 	vproc_carehead_t	*vchp,
@@ -413,12 +412,12 @@
 	struct vproc *vp;
 	int i;
 
+	for (i=0; i < vprochsz; i++) {
 #ifdef VPROC_RCU_LIST
-	rcu_read_lock();
+		rcu_read_lock();
 #else
-	VPROC_LIST_LOCK();
+		VPROC_LIST_LOCK();
 #endif
-	for (i=0; i < vprochsz; i++) {
 #ifdef VPROC_HASH_LIST
 #ifdef VPROC_RCU_LIST
 		list_for_each_entry_rcu(vp, &vproc_hash[i], vp_list) {
@@ -436,12 +435,12 @@
 			PVP(vp)->pvp_flag |= PV_IS_ORIGIN;
 			VPROC_UNLOCK_FLAG(vp, "vproc_setup_mark_origin_vprocs");
 		}
-	}
 #ifdef VPROC_RCU_LIST
-	rcu_read_unlock();
+		rcu_read_unlock();
 #else
-	VPROC_LIST_UNLOCK();
+		VPROC_LIST_UNLOCK();
 #endif
+	}
 }
 
 /*
@@ -473,7 +472,7 @@
 		VPROC_LIST_LOCK();
 #ifdef VPROC_HASH_LIST
 #ifdef VPROC_RCU_LIST
-		list_for_each_entry_rcu(vp, &vproc_hash[i], vp_list) {
+#error not supported
 #else
 		list_for_each_entry(vp, &vproc_hash[i], vp_list) {
 #endif

Index: rproc_svr_vproc.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/vproc/rproc_svr_vproc.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- rproc_svr_vproc.c	24 Mar 2009 04:26:28 -0000	1.16
+++ rproc_svr_vproc.c	27 Oct 2009 03:18:30 -0000	1.17
@@ -89,11 +89,7 @@
 	 */
 	error = rfork_pproc_unload_msg(rf_datap, flags, regs);
 	if (error) {
-#ifdef VPROC_RCU_LIST
-		vproc_dealloc(&vc->vp_rcu);
-#else
-		vproc_dealloc(vc);
-#endif
+		free_vproc(vc);
 		return error;
 	}
 
@@ -302,10 +298,18 @@
 	if (error)
 		return error;
 
+#ifdef TASK_HOLD_VPROC
+	/* Initialize p_vproc early for following path:
+	 * ssi_do_execve, dvp_set_exec
+	 */
+	write_lock_irq(&tasklist_lock);
+	procp->p_vproc = ve;
+	write_unlock_irq(&tasklist_lock);
+#endif
 	error = ssi_do_execve(fname, argv, envp, regs, 0);
 	/* Successful? */
 	if (error == 0)
-		current->ptrace &= ~PT_DTRACE;
+		procp->ptrace &= ~PT_DTRACE;
 	else
 		return error;
 
@@ -321,10 +325,9 @@
 	 * structure.
 	 */
 #ifdef VPROC_HOLD_ZERO_GET_TASK
-	if (pve->pvp_pproc) {
-		WARN_ON(PV_IS_ALIVE(pve));
-		put_task_struct(pve->pvp_pproc);
-	}
+#ifndef TASK_HOLD_VPROC
+	BUG_ON(pve->pvp_pproc);
+#endif
 	get_task_struct(procp);
 #endif
 	pve->pvp_pproc = procp;
@@ -364,9 +367,7 @@
 	bcopy(NSC_COMM(pve->pvp_pproc), pve->pvp_comm, 10);
 #endif
 	clinode =  (pve->pvp_pin >> NODESHIFT);
-	mb();
 	pve->pvp_pin &= ~(clinode << NODESHIFT);
-	mb();
 	ll_select =  (pve->pvp_pin >> (NODESHIFT - 4));
 	if (ll_select)
 		pve->pvp_pin &= ~(ll_select << (NODESHIFT - 4));
@@ -457,7 +458,6 @@
 		PVP_ADD_PARENT(PVP(vc), pve);
 #else
 		PVP(vc)->pvp_childl = pve->pvp_head_childl;
-		mb();
 		pve->pvp_head_childl = vc;
 #endif /* !VPROC_PVP_CHILD_LL */
 		VPROC_UNLOCK_ND_LIST_EXCL(ve, "rexecve_server");
@@ -481,7 +481,6 @@
 			if (vg == 0)
 				panic("rexecve_server: cannot find pgrp memb");
 			PVP(vg)->pvp_pgrpl = pve->pvp_head_pgrpl;
-			mb();
 			pve->pvp_head_pgrpl = vg;
 			VPROC_HOLD(ve, "rexecve_server(pgrp ldr on ldr node)");
 		}
@@ -508,7 +507,6 @@
 			if (vs == 0)
 				panic("rexecve_server: cannot find sess memb");
 			PVP(vs)->pvp_sessionl = pve->pvp_sessionl;
-			mb();
 			pve->pvp_sessionl = vs;
 			VPROC_HOLD(ve, "rexecve_server(sess ldr on ldr node)");
 		}
@@ -628,10 +626,16 @@
 	 * structure.
 	 */
 #ifdef VPROC_HOLD_ZERO_GET_TASK
-	if (pvm->pvp_pproc) {
-		WARN_ON(PV_IS_ALIVE(pvm));
-		put_task_struct(pvm->pvp_pproc);
-	}
+#ifndef TASK_HOLD_VPROC
+	/* SSI_XXX:
+	 * node1 pid 69315 (E) - dvp_rexecve(0x2,...), pproc_cleanup_process, schedule.
+	 * node1 pid 69315 sticks around; pvp_pproc has final reference.
+	 * node2 migrate 69315 to node1.
+	 * node1 "pid 69315" (R) - migrate_server, __put_task_struct, free_task, BUG.
+	 */
+	/* Fixed. pvp_pproc is NULL'ed out after migration */
+	BUG_ON(pvm->pvp_pproc);
+#endif
 	get_task_struct(procp);
 #endif
 	pvm->pvp_pproc = procp;
@@ -671,9 +675,7 @@
 	bcopy(NSC_COMM(pvm->pvp_pproc), pvm->pvp_comm, 10);
 #endif
 	clinode =  (pvm->pvp_pin >> NODESHIFT);
-	mb();
 	pvm->pvp_pin &= ~(clinode << NODESHIFT);
-	mb();
 	ll_select =  (pvm->pvp_pin >> (NODESHIFT - 4));
 	if (ll_select)
 		pvm->pvp_pin &= ~(ll_select << (NODESHIFT - 4));
@@ -688,12 +690,12 @@
 		vp = LOCATE_VPROC_PID(pvm->pvp_ppid,
 						    "perm svr parent");
 		if (vp == 0) {
-			printk("migrate_server: cannot find parent");
 			pvm->pvp_pproc = NULL;
+			VPROC_UNLOCK_EXCL(vm,"migrate_server");
 #ifdef VPROC_HOLD_ZERO_GET_TASK
 			put_task_struct(procp);
 #endif
-			VPROC_UNLOCK_EXCL(vm,"migrate_server");
+			printk("migrate_server: cannot find parent");
 			return -EREMOTE;
 		}
 	}
@@ -716,12 +718,12 @@
 		if (g == 0) {
 			if (pgrp_member_pid_cnt) {
 				pvm->pvp_pproc = NULL;
+				VPROC_UNLOCK_EXCL(vm, "migrate_server");
+				VPROC_RELE(fvp, "migrate_server");
+				VPROC_RELE(vp, "migrate_server");
 #ifdef VPROC_HOLD_ZERO_GET_TASK
 				put_task_struct(procp);
 #endif
-				VPROC_RELE(fvp, "migrate_server");
-				VPROC_RELE(vp, "migrate_server");
-				VPROC_UNLOCK_EXCL(vm, "migrate_server");
 				return -EREMOTE;
 			} else
 				panic("migrate_server: cannot find pgrp leader");
@@ -764,7 +766,6 @@
 		PVP_ADD_PARENT(PVP(vc), pvm);
 #else
 		PVP(vc)->pvp_childl = pvm->pvp_head_childl;
-		mb();
 		pvm->pvp_head_childl = vc;
 #endif /* !VPROC_PVP_CHILD_LL */
 		VPROC_UNLOCK_ND_LIST_EXCL(vm, "migrate_server");
@@ -793,7 +794,6 @@
 				PVP(vg)->pvp_flag |= PV_EXITING|PV_WAITED;
 			}
 			PVP(vg)->pvp_pgrpl = pvm->pvp_head_pgrpl;
-			mb();
 			pvm->pvp_head_pgrpl = vg;
 			VPROC_HOLD(vm, "migrate_server(pgrp ldr on ldr node)");
 		}
@@ -820,7 +820,6 @@
 			if (vs == 0)
 				panic("migrate_server: cannot find sess memb");
 			PVP(vs)->pvp_sessionl = pvm->pvp_sessionl;
-			mb();
 			pvm->pvp_sessionl = vs;
 			VPROC_HOLD(vm, "migrate_server(sess ldr on ldr node)");
 		}
@@ -840,7 +839,6 @@
 		if (vc == 0)
 			panic("migrate_server: cannot find orig child");
 		PVP(vc)->pvp_oclist = pvm->pvp_head_oclist;
-		mb();
 		pvm->pvp_head_oclist = vc;
 	}
 

Index: rproc_server_pproc.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/vproc/rproc_server_pproc.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- rproc_server_pproc.c	24 Mar 2009 04:26:28 -0000	1.13
+++ rproc_server_pproc.c	27 Oct 2009 03:18:30 -0000	1.14
@@ -49,6 +49,7 @@
 
 	INIT_EVENT(&svrargs->childdone);
 
+	smp_mb(); /* barrier ensures rvp_remote_args_t visible to thread */
 	error = kernel_thread_with_pid((void *)svrfunc, svrargs,
 				       clone_flags, svrargs->childpid);
 	if (error == svrargs->childpid) {
@@ -130,11 +131,7 @@
 		ve = re_args->rexecve_args.vprocp;
 		pve = PVP(ve);
 
-#ifdef VPROC_HOLD_ZERO_GET_TASK
-		if (pve->pvp_pproc)
-			put_task_struct(pve->pvp_pproc); 
-#endif
-		pve->pvp_pproc = NULL;
+		/* pve->pvp_pproc = NULL; */
 
 		/*
 		 * The child process encountered an error while attempting to
@@ -143,7 +140,18 @@
 		pproc_remove_process();
 
 #ifdef VPROC_HOLD_ZERO_GET_TASK
-		get_task_struct(current);
+		if (pve->pvp_pproc) {
+#ifdef TASK_HOLD_VPROC
+			BUG();
+#else
+			if (pve->pvp_pproc != current) {
+				WARN_ON(PV_IS_ALIVE(pve));
+				put_task_struct(pve->pvp_pproc);
+				get_task_struct(current);
+			}
+#endif
+		} else
+			get_task_struct(current);
 #endif
 		pve->pvp_pproc = current;
 
@@ -183,7 +191,9 @@
 	struct move_data *d = mi_args->migrate_args.data;
 	int is_sigmig = mi_args->migrate_args.is_sigmigrate;
 	int error;
+#ifndef VPROC_HOLD_ZERO_GET_TASK
 	struct pvproc *pvm;
+#endif
 	struct arch_regs_stack regs;
 
 	error = move_init_state(d);
@@ -201,8 +211,8 @@
 		 * The child process encountered an error while attempting to
 		 * setup so destroy the child process.
 		 */
-		pvm = PVP(vm);
 #ifndef VPROC_HOLD_ZERO_GET_TASK
+		pvm = PVP(vm);
 		pvm->pvp_pproc = NULL;
 #endif
 		write_lock_irq(&tasklist_lock);
@@ -212,8 +222,11 @@
 
 		pproc_remove_process();
 
+		write_lock_irq(&tasklist_lock);
 		p->exit_state = EXIT_ZOMBIE;
 		p->group_leader = p;	/* prevent report state */
+		write_unlock_irq(&tasklist_lock);
+
 		VPROC_RELE(vm, "perm svr_migrate()");
 		pproc_cleanup_process();
 		panic("%s: return from destroyed process\n", __FUNCTION__);

Index: reopen.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/vproc/reopen.c,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -d -r1.32 -r1.33
--- reopen.c	24 Mar 2009 04:26:28 -0000	1.32
+++ reopen.c	27 Oct 2009 03:18:30 -0000	1.33
@@ -56,6 +56,9 @@
 #include <cluster/gen/cfs.h>
 #include <cluster/ssi/cfs/cfsfh.h>
 #endif
+#ifdef CFS_FLOCK
+#include <cluster/ssi/cfs/cfs_fs.h>
+#endif
 #include <cluster/ssi/cfs/cfs_clnt.h>
 
 #include <cluster/gen/reopen.h>
@@ -201,8 +204,9 @@
  * the mirror locks can be established on the destination node.
  */
 static int 
-reop_export_locks(struct inode *ip, filockdata_list_t *flckp, int optype)
+reop_export_locks(struct inode *ip, struct pathdata *path, int optype)
 {
+	filockdata_list_t	*flckp = &path->lckdata_info;
 	struct file_lock 	*fl;
 	struct filockdata	*lockp;
 	int		count;
@@ -211,13 +215,22 @@
 	 * creates the mirror locks, due to the way the base code works.
 	 */
 	/* Check if locks need to be exported. */
+#ifndef CFS_FLOCK
 	if (!(cfs_inode_is_cfs(ip) && (optype == REOP_REXEC_MIG) &&
 						(ip->i_flock != NULL))) {
+#else
+	if (!cfs_inode_is_cfs(ip) || optype != REOP_REXEC_MIG || ip->i_flock == NULL) {
+#endif
 		flckp->filockdata_list_t_val = NULL;
 		flckp->filockdata_list_t_len = 0;
 		return 0;
 	}
 
+	/* SSI_XXX: need CTV lock here? */
+#ifdef SSI_CFS_SKIP
+	clms_snap_locked_ctv((ctv_t *)&(path->ctv));
+#endif
+
 	/* count the number of locks that need to be exported */
 	lock_kernel();
 	for (fl = ip->i_flock, count = 0; fl; fl = fl->fl_next) {
@@ -228,11 +241,21 @@
 	unlock_kernel();
 
 	flckp->filockdata_list_t_len = count;
+#ifdef CFS_FLOCK
+	if (!count) {
+		flckp->filockdata_list_t_val = NULL;
+		return 0;
+	}
+#endif
 
 	/* Allocate memory for export lock data */
 	lockp = kzmalloc(count * sizeof(*lockp), GFP_USER);
-	if (!lockp)
+	if (!lockp) {
+#ifdef SSI_CFS_SKIP
+		clms_unlock_ctv();
+#endif
 		return -ENOMEM;
+	}
 
 	flckp->filockdata_list_t_val = lockp;
 
@@ -250,6 +273,10 @@
 	}
 	unlock_kernel();
 
+#ifdef SSI_CFS_SKIP
+	clms_unlock_ctv();
+#endif
+
 	/* check the we havent overflowed the memory allocated */
 	SSI_ASSERT((lockp - flckp->filockdata_list_t_val) ==  count);
 	return 0;
@@ -264,23 +291,19 @@
 int
 reop_import_locks(struct file *filp, filockdata_list_t *flckp, ctv_t ctv)
 {
+	struct file_lock fl;
 	struct filockdata *lockp;
-	int count;
-	int error = 0;
-	int ret = 0;
-	int lock_retries = 0;
-	struct inode *ip = filp->f_dentry->d_inode;
-	struct file_lock flock, *fl = &flock;
+	int count, ret, error = 0;
+	int lock_retries;
 
 	/* We use to skip soft mounted fileystems, but linux always
 	 * creates the mirror locks, due to the way the base code works.
 	 */
-	SSI_ASSERT(cfs_inode_is_cfs(ip) || (flckp->filockdata_list_t_len == 0));
+	SSI_ASSERT(cfs_inode_is_cfs(filp->f_dentry->d_inode) || (flckp->filockdata_list_t_len == 0));
 
 	/* Check to see if locks need to be imported */
-	if (!cfs_inode_is_cfs(ip) || flckp->filockdata_list_t_len == 0) {
-		return error;
-	}
+	if (!cfs_inode_is_cfs(filp->f_dentry->d_inode) || flckp->filockdata_list_t_len == 0)
+		return 0;
 
 	/* SSI_XXX: Do I really need the ctv locked across the import? */
 	/* SSI_XXX: Isn't the issue preventing failover of the mount,
@@ -295,31 +318,38 @@
 	 * can't have failed, we can install the mirror locks with
 	 * the assurance that the CFS server knows about these locks too.
 	 */
+#ifdef SSI_CFS_SKIP
 	if (!clms_compare_locked_ctv(CLMS_CMP_CTV_DOWNS, ctv)) {
 		clms_unlock_ctv();
 		error = -ERFB_TRYAGAIN;
 		goto out;
 	}
-
-	locks_init_lock(fl);
+#endif
+	locks_init_lock(&fl);
 	lockp = (filockdata *)flckp->filockdata_list_t_val;
 	for(count=0 ; count < flckp->filockdata_list_t_len; count++, lockp++) {
 
-		fl->fl_start = lockp->lkdata_start;
-		fl->fl_end = lockp->lkdata_end;
-
-		fl->fl_owner = current->files;
+		fl.fl_owner = current->files;
 		/* current->pid might be ready, but don't depend on it here */
-		fl->fl_pid = lockp->lkdata_pid;
-		fl->fl_file = filp;
-		fl->fl_flags = lockp->lkdata_flags;
-		SSI_ASSERT(fl->fl_flags == FL_POSIX);
-		fl->fl_type = lockp->lkdata_type;
+		fl.fl_pid = lockp->lkdata_pid;
+		fl.fl_file = filp;
+		fl.fl_flags = lockp->lkdata_flags;
+#ifndef CFS_FLOCK
+		SSI_ASSERT(fl.fl_flags == FL_POSIX);
+#endif
+		fl.fl_type = lockp->lkdata_type;
+		fl.fl_start = lockp->lkdata_start;
+		fl.fl_end = lockp->lkdata_end;
 
 		lock_retries = 0;
 retry_mirror_locks:
 		/* Acquire the mirror lock on destination node*/
-		error = posix_lock_file(filp, fl);
+#ifdef CFS_FLOCK
+		fl.fl_flags &= ~FL_SLEEP;
+		error = do_cfs_lock(&fl);
+#else
+		error = posix_lock_file(filp, &fl);
+#endif
 
 		/* We don't wait since it can't conflict! */
 		SSI_ASSERT(error != -EAGAIN);
@@ -338,7 +368,6 @@
 			/* SSI_XXX: Scary with ctv lock held */
 			set_current_state(TASK_UNINTERRUPTIBLE);
 			schedule_timeout(5);
-
 			goto retry_mirror_locks;
 		}
 	}
@@ -346,24 +375,29 @@
 	if (error) {
 		for(lockp = (filockdata *)flckp->filockdata_list_t_val; 
 				count > 0; count-- , lockp++) {
-			fl->fl_start = lockp->lkdata_start;
-			fl->fl_end = lockp->lkdata_end;
-
-			fl->fl_owner = current->files;
+			fl.fl_owner = current->files;
 			/* current->pid might be ready, but don't depend on it here */
-			fl->fl_pid = lockp->lkdata_pid;
-			fl->fl_file = filp;
-			fl->fl_flags = lockp->lkdata_flags;
-			SSI_ASSERT(fl->fl_flags == FL_POSIX);
-			fl->fl_type = F_UNLCK;
+			fl.fl_pid = lockp->lkdata_pid;
+			fl.fl_file = filp;
+			fl.fl_flags = lockp->lkdata_flags;
+			fl.fl_type = F_UNLCK;
+			fl.fl_start = lockp->lkdata_start;
+			fl.fl_end = lockp->lkdata_end;
 
-			ret = posix_lock_file(filp, fl);
+#ifdef CFS_FLOCK
+			ret = do_cfs_lock(&fl);
+#else
+			SSI_ASSERT(fl->fl_flags == FL_POSIX);
+			ret = posix_lock_file(filp, &fl);
+#endif
 			SSI_ASSERT(!ret);
 		}
 	}
 
+#ifdef SSI_CFS_SKIP
 	clms_unlock_ctv();
 out:
+#endif
 #ifdef REOPDEBUG
 	printk(KERN_ERR "cli_reop_import_locks returned with error %d\n", error);
 #endif
@@ -493,11 +527,9 @@
 			goto page_free_out;
 		}
 	}
-	/* Export locks if needed */
-	clms_snap_locked_ctv((ctv_t *)&(path->ctv));
-	error = reop_export_locks(dentry->d_inode, &path->lckdata_info, optype);
-	clms_unlock_ctv();
 
+	/* Export locks if needed */
+	error = reop_export_locks(dentry->d_inode, path, optype);
 	if (error)
 		goto page_free_out;
 
@@ -567,6 +599,9 @@
 	unsigned long ino)
 #endif
 {
+#ifdef SSI_LOOKUP_DENTRY_HASH
+	struct qstr this;
+#endif
 #ifndef REOP_EXPORT_PATH_SVRNODE
 	unsigned long svrnode;
 	int count, ctr;
@@ -608,12 +643,18 @@
 	*name = pathname;
 #endif
 
-#ifndef SSI_LOOKUP_DENTRY_HASH
 	nd->last_type = LAST_ROOT;
 	nd->flags = 0;
-#endif
 	nd->dentry = dget(nd->mnt->mnt_root);
 
+#ifdef SSI_LOOKUP_DENTRY_HASH
+	/* its a pipe or socket cant do normal path_walk()
+	 * since dentry gets hashed by ino number, not name
+	 */
+	this.name = pathname;
+	this.len = strlen(pathname);
+	this.hash = ino; /* pipe or socket */
+#endif
 #ifndef REOP_EXPORT_PATH_SVRNODE
 	/*
 	 * SSI_XXX: Should probably pass in the svrnode instead of the
@@ -624,8 +665,9 @@
 	svrnode = (ino >> 24);
 #endif
 	if (this_node == svrnode) {
-		struct qstr this;
 		struct dentry *dentry;
+#ifndef SSI_LOOKUP_DENTRY_HASH
+		struct qstr this;
 
 		/* its a pipe or socket cant do normal path_walk()
 		 * since dentry gets hashed by ino number, not name
@@ -633,6 +675,7 @@
 		this.name = pathname;
 		this.len = strlen(pathname);
 		this.hash = ino;
+#endif
 		dentry = d_lookup(nd->dentry, &this);
 #ifdef REOPDEBUG
 		printk(KERN_DEBUG "reop_import_pathinit: d_lookup() dentry=%p name=%s hash=%d\n",
@@ -646,25 +689,23 @@
 	}
 #ifdef SSI_LOOKUP_DENTRY_HASH
 	else {
-		struct path next;
-		struct qstr this;
+		struct path {
+			struct vfsmount *mnt;
+			struct dentry *dentry;
+		} next;
 		int ret;
-
-		/* SSI_XXX: redundant w/ above */
-		this.name = pathname;
-		this.len = strlen(pathname);
-		this.hash = ino; /* pipe or socket */
+		extern int do_lookup(struct nameidata *, struct qstr *, struct path *);
 
 		ret = do_lookup(nd, &this, &next);
 #ifdef REOPDEBUG
 		printk(KERN_DEBUG "reop_import_pathinit: do_lookup() ret=%d name=%s hash=%d\n",
-					ret, pathname, (int)ino);
+				ret, pathname, (int)ino);
 #endif
-		if (ret)
-			return ret;
-		dput(nd->dentry);
-		nd->dentry = next.dentry;
-		return 0;
+		if (!ret) {
+			dput(nd->dentry);
+			nd->dentry = next.dentry;
+		}
+		return ret;
 	}
 	/* not reached */
 	BUG();
@@ -754,7 +795,6 @@
 		if (cp != NULL && !strncmp(cp, "/dev/", 5)) {
 			/* Some callers free only pathname */
 			save_pathname = path->pathname;
-			mb();
 			path->pathname = cp;
 		}
 	}
@@ -781,13 +821,11 @@
 	if (!path->deleted) {
 #ifdef REOP_EXPORT_PATH_SVRNODE
 		ret = reop_import_pathinit(&pathname, &nd, path->svrnode, path->ino);
-#else
-		ret = reop_import_pathinit(&pathname, &nd, path->ino);
-#endif
 		if (ret < 0)
-#ifdef REOP_EXPORT_PATH_SVRNODE
 			goto out_fail;
 #else
+		ret = reop_import_pathinit(&pathname, &nd, path->ino);
+		if (ret < 0)
 			return error;
 #endif
 		error = 0;
@@ -1060,7 +1098,6 @@
 		path->svrnode = svr;
 #endif
 	save_nc = current->node_context;
-	mb();
 	current->node_context = svr;
 #ifdef REOPDEBUG
 	if (svr != save_nc)

Index: vp_init.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/vproc/vp_init.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- vp_init.c	9 Feb 2009 05:00:36 -0000	1.8
+++ vp_init.c	27 Oct 2009 03:18:30 -0000	1.9
@@ -51,7 +51,8 @@
 #endif
 
 #ifdef VPROC_LIST_SPINLOCK
-DEFINE_SPINLOCK(vproc_list_lock);	/* Lock for free list and hash table */
+/* Lock for free list and hash table */
+__cacheline_aligned_in_smp DEFINE_SPINLOCK(vproc_list_lock);
 #else
 LOCK_T vproc_list_lock;		/* Lock for free list and hash table */
 #endif

Index: rproc_cli_vproc.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/vproc/rproc_cli_vproc.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- rproc_cli_vproc.c	3 Feb 2009 06:18:13 -0000	1.10
+++ rproc_cli_vproc.c	27 Oct 2009 03:18:30 -0000	1.11
@@ -194,7 +194,6 @@
 	PVP_ADD_PARENT(pvc, pvp);
 #else
 	pvc->pvp_childl = pvp->pvp_head_childl;
-	mb();
 	pvp->pvp_head_childl = vc;
 #endif /* !VPROC_PVP_CHILD_LL */
 	VPROC_UNLOCK_ND_LIST_EXCL(vp, "cli_rfork");
@@ -403,7 +402,6 @@
 		register struct vproc *vc = pve->pvp_head_childl;
 
 		pve->pvp_head_childl = PVP(vc)->pvp_childl;
-		mb();
 		PVP(vc)->pvp_childl = NULL;
 		VPROC_RELE(vc, "rexecve (child on parent node)");
 	}
@@ -423,7 +421,6 @@
 			register struct vproc *vg = pve->pvp_head_pgrpl;
 
 			pve->pvp_head_pgrpl = PVP(vg)->pvp_pgrpl;
-			mb();
 			PVP(vg)->pvp_pgrpl = NULL;
 			VPROC_RELE(vg, "rexecve (pgrp member on ldr node)");
 			VPROC_RELE(ve, "rexecve (pgrp leader on ldr node)");
@@ -442,7 +439,6 @@
 			register struct vproc *vs = pve->pvp_sessionl;
 
 			pve->pvp_sessionl = PVP(vs)->pvp_sessionl;
-			mb();
 			PVP(vs)->pvp_sessionl = NULL;
 			VPROC_RELE(vs, "rexecve (sess member on ldr node)");
 			VPROC_RELE(ve, "rexecve (sess leader on ldr node)");
@@ -459,19 +455,24 @@
 		register struct vproc *vc = pve->pvp_head_oclist;
 
 		pve->pvp_head_oclist = PVP(vc)->pvp_oclist;
-		mb();
 		PVP(vc)->pvp_oclist = NULL;
 		VPROC_RELE(vc, "rexecve (orig child on parent node)");
 	}
 	VPROC_UNLOCK_ND_LIST_EXCL(ve, "rexecve");
 
-#ifndef VPROC_HOLD_ZERO_GET_TASK
 	/*
 	 * NULL out the physical proc structure pointer now that
 	 * that the process has been moved.
 	 */
+#ifdef TASK_HOLD_VPROC
+	/* No need to NULL out pvp_pproc since PV_PROCESS flag is disabled */
+	/* vproc_giveback() needs pvp_pproc for delayed vproc dealloc */
+	put_task_struct(pve->pvp_pproc);
+#else
+#ifndef VPROC_HOLD_ZERO_GET_TASK
 	pve->pvp_pproc = NULL;
 #endif
+#endif
 
 	/*
 	 * Remove the local incarnation of the process because
@@ -674,7 +675,6 @@
 		register struct vproc *vc = pvm->pvp_head_childl;
 
 		pvm->pvp_head_childl = PVP(vc)->pvp_childl;
-		mb();
 		PVP(vc)->pvp_childl = NULL;
 		VPROC_RELE(vc, "migrate (child on parent node)");
 	}
@@ -694,7 +694,6 @@
 			register struct vproc *vg = pvm->pvp_head_pgrpl;
 
 			pvm->pvp_head_pgrpl = PVP(vg)->pvp_pgrpl;
-			mb();
 			PVP(vg)->pvp_pgrpl = NULL;
 			VPROC_RELE(vg, "migrate (pgrp member on ldr node)");
 			VPROC_RELE(vm, "migrate (pgrp leader on ldr node)");
@@ -713,7 +712,6 @@
 			register struct vproc *vs = pvm->pvp_sessionl;
 
 			pvm->pvp_sessionl = PVP(vs)->pvp_sessionl;
-			mb();
 			PVP(vs)->pvp_sessionl = NULL;
 			VPROC_RELE(vs, "migrate (sess member on ldr node)");
 			VPROC_RELE(vm, "migrate (sess leader on ldr node)");
@@ -730,20 +728,25 @@
 		register struct vproc *vc = pvm->pvp_head_oclist;
 
 		pvm->pvp_head_oclist = PVP(vc)->pvp_oclist;
-		mb();
 		PVP(vc)->pvp_oclist = NULL;
 		VPROC_RELE(vc, "migrate (orig child on parent node)");
 	}
 
 	VPROC_UNLOCK_ND_LIST_EXCL(vm, "migrate");
 
-#ifndef VPROC_HOLD_ZERO_GET_TASK
 	/*
 	 * NULL out the physical proc structure pointer now that
 	 * that the process has been moved.
 	 */
+#ifdef TASK_HOLD_VPROC
+	/* No need to NULL out pvp_pproc since PV_PROCESS flag is disabled */
+	/* vproc_giveback() needs pvp_pproc for delayed vproc dealloc */
+	put_task_struct(pvm->pvp_pproc);
+#else
+#ifndef VPROC_HOLD_ZERO_GET_TASK
 	pvm->pvp_pproc = NULL;
 #endif
+#endif
 
 	/*
 	 * Remove the local incarnation of the process because

Index: dvp_init.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/vproc/dvp_init.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- dvp_init.c	24 Mar 2009 04:26:28 -0000	1.16
+++ dvp_init.c	27 Oct 2009 03:18:29 -0000	1.17
@@ -157,6 +157,14 @@
 	if (pid < 0)
 		return NULL;
 
+#ifndef VPROC_LOCKING_CONTEXT_FIX
+	if ((flags & LVP_NOFAIL) || !(flags & LVP_ORIGIN))
+#else
+	if ((flags & LVP_NOFAIL) ||
+	    (!(flags & LVP_ORIGIN) && !PID_IS_AT_ORIGIN(pid)))
+#endif
+		might_sleep();
+
 #ifdef VPROC_RCU_LIST
 	/* No longer support LVP_NOLOCK flag. We are lockless. */
 	BUG_ON(flags & LVP_NOLOCK);
@@ -183,13 +191,10 @@
 		 */
 		if (!(flags & LVP_NOFAIL) &&
 		     ((flags & LVP_ORIGIN) || PID_IS_AT_ORIGIN(pid))) {
-			vp = NULL;
+			/* vp = NULL; */
 			goto out;
 		}
 
-#ifdef VPROC_RCU_LIST
-		down(&mutex);
-#endif
 		/*
 		 * Since this is not the origin node of the pid, the process
 		 * could have migrated to a different node.  We create a vproc
@@ -197,16 +202,15 @@
 		 * a vproc in hand.
 		 */
 		if ((nvp = vproc_alloc()) == NULL) {
-#ifdef VPROC_RCU_LIST
-			up(&mutex);
-#endif
 			printk("locate_vproc_pid(): "
 			       "vproc_alloc() failure\n");
-			vp = NULL;
+			/* vp = NULL; */
 			goto out;
 		}
 
-#ifndef VPROC_RCU_LIST
+#ifdef VPROC_RCU_LIST
+		down(&mutex);
+#else
 		if (!(flags & LVP_NOLOCK))
 			VPROC_LIST_LOCK();
 #endif
@@ -264,11 +268,7 @@
 	 * it's now safe to de_allocate it (now that the lists are unlocked).
 	 */
 	if (nvp != NULL)
-#ifdef VPROC_RCU_LIST
-		VPROC_RELE(nvp, str);
-#else
-		vproc_dealloc(nvp);
-#endif
+		free_vproc(nvp);
 
 out:
 	return(vp);
@@ -344,7 +344,7 @@
 	VPROC_HOLD_MOVEMENT_INIT(v);
 	VPROC_WAIT_EVENT_INIT(v);
 #else
-	/* SSI_XXX: Create macros for these... */
+	/* TODO: Create macros for these... */
 	pvp->pvp_movement_lock.ml_flag = 0;
 	pvp->pvp_movement_lock.ml_shr_count = 0;
 	pvp->pvp_movement_lock.ml_excl_count = 0;

Index: nd_carelist.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/vproc/nd_carelist.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- nd_carelist.c	24 Mar 2009 04:26:28 -0000	1.8
+++ nd_carelist.c	27 Oct 2009 03:18:30 -0000	1.9
@@ -27,12 +27,34 @@
 #include <cluster/synch.h>
 #include <linux/nd_carelist.h>
 
+#ifdef VPROC_CAREHEAD_KMEM_CACHE
+static kmem_cache_t *vproc_carehead_cachep;
+
+static int __init vproc_carehead_init(void)
+{
+	vproc_carehead_cachep = kmem_cache_create("vproc_carehead",
+				sizeof(vproc_carehead_t), 0,
+				SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|SLAB_PANIC,
+				NULL, NULL);
+	if (!vproc_carehead_cachep)
+		return -ENOMEM;
+
+	return 0;
+}
+module_init(vproc_carehead_init);
+#endif
+
 vproc_carehead_t *
 vproc_carehead_alloc(void)
 {
 	vproc_carehead_t *vchp;
 
+#ifdef VPROC_CAREHEAD_KMEM_CACHE
+	vchp = kmem_cache_alloc(vproc_carehead_cachep, GFP_KERNEL|__GFP_NOFAIL);
+	bzero(vchp, kmem_cache_size(vproc_carehead_cachep));
+#else
 	vchp = kzmalloc_nofail(sizeof(vproc_carehead_t));
+#endif
 
 	return vchp;
 }
@@ -41,15 +63,42 @@
 vproc_carehead_dealloc(
 	vproc_carehead_t *vchp)
 {
+#ifdef VPROC_CAREHEAD_KMEM_CACHE
+	kmem_cache_free(vproc_carehead_cachep, vchp);
+#else
 	kfree((void *)vchp);
+#endif
 }
 
+#ifdef VPROC_CAREDATA_KMEM_CACHE
+static kmem_cache_t *vproc_caredata_cachep;
+
+static int __init vproc_caredata_init(void)
+{
+	vproc_caredata_cachep = kmem_cache_create("vproc_caredata",
+				sizeof(vproc_caredata_t), 0,
+				SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|SLAB_PANIC,
+				NULL, NULL);
+	if (!vproc_caredata_cachep)
+		return -ENOMEM;
+
+	return 0;
+}
+module_init(vproc_caredata_init);
+#endif
+
 vproc_caredata_t *
 vproc_caredata_alloc(
 	size_t num)
 {
 	vproc_caredata_t *vcdp;
 
+#ifdef VPROC_CAREDATA_KMEM_CACHE
+	if (likely(num == 1)) {
+		vcdp = kmem_cache_alloc(vproc_caredata_cachep, GFP_KERNEL|__GFP_NOFAIL);
+		bzero(vcdp, kmem_cache_size(vproc_caredata_cachep));
+	} else
+#endif
 	vcdp = kzmalloc_nofail(num * sizeof(vproc_caredata_t));
 
 	return vcdp;
@@ -60,9 +109,17 @@
 	vproc_caredata_t *vcdp,
 	size_t num)
 {
+#ifdef VPROC_CAREDATA_KMEM_CACHE
+	if (likely(num == 1))
+		kmem_cache_free(vproc_caredata_cachep, vcdp);
+	else
+#endif
 	kfree((void *)vcdp);
 }
 
+/* Caller holds vproc_objhash_lock or
+ * vod_carehash_rwlock or vod_carequeue_mutex
+ */
 void
 vproc_caredata_copy(
 	vproc_caredata_t *dest_vcdp,
@@ -73,6 +130,9 @@
 	dest_vcdp->vcd_prev = NULL;
 }
 
+/* Caller holds vproc_objhash_lock or
+ * vod_carehash_rwlock or vod_carequeue_mutex
+ */
 int
 vproc_caredata_comp(
 	vproc_caredata_t *vcdp1,
@@ -91,6 +151,15 @@
 	return 1;
 }
 
+/* Caller holds vproc_objhash_lock or
+ * vod_carehash_rwlock or vod_carequeue_mutex
+ *
+ * ... with the exception of rebuild path:
+ * 			(vproc_slave_daemon)
+ * EX pvp_nd_list_lock	(vproc_slave_carelist_create)
+ *			(...)
+ *			(vproc_caredata_add)
+ */
 void
 vproc_caredata_add(
 	vproc_carehead_t	*vchp,
@@ -102,13 +171,13 @@
 	if (vchp->vch_caredatap)
 		vchp->vch_caredatap->vcd_prev = vcdp;
 
-#ifdef VPROC_ND_CARELIST_RACE_FIX
-	mb();
-#endif
 	vchp->vch_caredatap = vcdp;
 	vchp->vch_carecount++;
 }
 
+/* Caller holds vproc_objhash_lock or
+ * vod_carehash_rwlock or vod_carequeue_mutex
+ */
 void
 vproc_caredata_remove(
 	vproc_carehead_t	*vchp,
@@ -124,12 +193,20 @@
 	vchp->vch_carecount--;
 
 #ifdef VPROC_ND_CARELIST_RACE_FIX
-	mb();
+	rmb();
 #endif
 	vcdp->vcd_prev = NULL;
 	vcdp->vcd_next = NULL;
 }
 
+/* Caller holds vproc_objhash_lock or
+ * vod_carehash_rwlock or vod_carequeue_mutex
+ *
+ * ... with the exception of rebuild path:
+ * 	(vproc_slave_daemon)
+ *	(vproc_proc_origin_cleanup)
+ *	(vproc_caredata_get_next)
+ */
 vproc_caredata_t *
 vproc_caredata_get_next(
 	vproc_carehead_t	*vchp,
@@ -141,6 +218,9 @@
 		return vchp->vch_caredatap;
 }
 
+/* Caller holds vproc_objhash_lock or
+ * vod_carehash_rwlock or vod_carequeue_mutex
+ */
 vproc_caredata_t *
 vproc_caredata_find(
 	vproc_carehead_t	*vchp,
@@ -158,6 +238,12 @@
 	return vcdcurr;
 }
 
+/* Caller holds vproc_objhash_lock or
+ * vod_carehash_rwlock or vod_carequeue_mutex
+ * ... with the exception of rebuild path:
+ * 	(vproc_slave_daemon)
+ *	(vproc_carelist_release)
+ */
 void
 vproc_carelist_release(
 	vproc_carehead_t	*vchp)
@@ -174,6 +260,9 @@
 	vproc_carehead_dealloc(vchp);
 }
 
+/* Caller holds vproc_objhash_lock or
+ * vod_carehash_rwlock or vod_carequeue_mutex
+ */
 void
 vproc_carelist_package(
 	vproc_carehead_t *vchp,
@@ -186,6 +275,8 @@
 #ifdef VPROC_CARECOUNT_FIX
 	size_t carecount, cares_packed;
 
+	might_sleep();
+
 	/* SSI_XXX: vproc_caredata_alloc() bounded by size_t */
 	BUG_ON(vchp->vch_carecount > UINT_MAX);
 
@@ -243,6 +334,9 @@
 	}
 }
 
+/* Caller holds vproc_objhash_lock or
+ * vod_carehash_rwlock or vod_carequeue_mutex
+ */
 void
 vproc_carehead_list_add(
 	vproc_carehead_t	**vchlistpp,
@@ -255,6 +349,9 @@
 	*vchlistpp = vchp;
 }
 
+/* Caller holds vproc_objhash_lock or
+ * vod_carehash_rwlock or vod_carequeue_mutex
+ */
 void
 vproc_carehead_list_remove(
 	vproc_carehead_t	**vchlistpp,
@@ -269,12 +366,15 @@
 		vchp->vch_next->vch_prev = vchp->vch_prev;
 
 #ifdef VPROC_ND_CARELIST_RACE_FIX
-	mb();
+	rmb();
 #endif
 	vchp->vch_prev = NULL;
 	vchp->vch_next = NULL;
 }
 
+/* Caller holds vproc_objhash_lock or
+ * vod_carehash_rwlock or vod_carequeue_mutex
+ */
 vproc_carehead_t *
 vproc_carehead_list_find(
 	vproc_carehead_t	*vchlistp,
@@ -295,6 +395,9 @@
 	return vchcurr;
 }
 
+/* Caller holds vproc_objhash_lock or
+ * vod_carehash_rwlock or vod_carequeue_mutex
+ */
 void
 vproc_carehead_list_release(
 	vproc_carehead_t	*vchlistp)

Index: nd_slave.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/vproc/nd_slave.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- nd_slave.c	24 Mar 2009 04:26:28 -0000	1.11
+++ nd_slave.c	27 Oct 2009 03:18:30 -0000	1.12
@@ -400,7 +400,7 @@
 #ifdef VPROC_RCU_LIST
 		list_for_each_entry_rcu(vp, &vproc_hash[i], vp_list) {
 #ifdef VPROC_LIST_SPINLOCK
-			if (!VPROC_HOLD_AND_CHECK(vp, "vproc_slave_carelist_create"))
+			if (!__vproc_hold_and_check(vp))
 				continue;
 #endif
 #else
@@ -592,8 +592,10 @@
 	vproc_carelist_release(slave_vchp);
 	vproc_carelist_release(cprocfs_vchp);
 
-	if (vnsap->is_daemon)
+	if (vnsap->is_daemon) {
+		kfree(vnsap);
 		exit_daemon_proc();
+	} /* caller responsible for de-alloc vnsap */
 }
 
 static void
@@ -611,6 +613,7 @@
 		       " slave daemon error %d\n", error);
 		vnsap->is_daemon = FALSE;
 		vproc_slave_daemon((void *)vnsap);
+		kfree(vnsap);
 	}
 }
 
@@ -694,18 +697,20 @@
 	nsc_nlcookie_t cookie;
 	clusternode_t node;
 
+	vnsap = kmalloc_nofail(sizeof(*vnsap));
 	NSC_NLCOOKIE_INIT(&cookie);
 	while ((node = NSC_NODELIST_GET_NEXT(&cookie, nodelist))
 							!= CLUSTERNODE_INVAL) {
-		vnsap = kzmalloc_nofail(sizeof(vproc_slave_args_t));
-
+		vnsap->is_daemon = FALSE;
+		vnsap->clms_handle = NULL;
+		vnsap->service = 0;
 		vnsap->trans_node = node;
 		vnsap->surrogate_node = surrogate_node;
 		vnsap->trans_type = VPROC_FAILOVER;
-		vnsap->is_daemon = FALSE;
 
 		vproc_slave_daemon(vnsap);
 	}
+	kfree(vnsap);
 
 	return 0;
 }

Index: nd_cleanup.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/vproc/nd_cleanup.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- nd_cleanup.c	24 Mar 2009 04:26:28 -0000	1.9
+++ nd_cleanup.c	27 Oct 2009 03:18:30 -0000	1.10
@@ -182,8 +182,16 @@
 	}
 #endif
 
+#ifdef VPROC_RELEASE__REFCNT_RACE_FIX
+	vp = LOCATE_VPROC_PID_ORIGIN((pid_t)vcdp->vcd_target,
+				     "vproc_should_pack_care");
+	/* new vproc from LOCATE_VPROC_PID_NOFAIL has no flags anyway */
+	if (!vp)
+		return 1;
+#else
 	vp = LOCATE_VPROC_PID_NOFAIL((pid_t)vcdp->vcd_target,
 				     "vproc_should_pack_care");
+#endif
 	pvp = PVP(vp);
 
 	if (vcdp->vcd_flags & VPROC_CARE_SESSION_MEMBER) {
@@ -541,8 +549,12 @@
 
 	if (error) {
 		/* if parent no longer exists then reassign to init process */
+#ifdef VPROC_RELEASE__REFCNT_RACE_FIX
+		SSI_ASSERT(ppid != 1);
+#endif
 		vp = VPROCPTR(1);
 		error = PVPOP_ADD_CHILD_TO_PARENT(vp, cvp, PVWS_SGHOST, 0);
+		SSI_ASSERT(!error);
 	}
 	PVPOP_REPORT_STATE(vp, cvp, &sig, NULL, VPROC_GHOST);
 

Index: pproc_subr.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/vproc/pproc_subr.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- pproc_subr.c	3 Feb 2009 06:18:13 -0000	1.11
+++ pproc_subr.c	27 Oct 2009 03:18:30 -0000	1.12
@@ -107,20 +107,33 @@
  * Calling/Exit State:
  *	None.
  */
+/* Called with VPROC_HOLD_MOVEMENT */
 int pproc_setctty(struct task_struct *p, dev_t cttydev, clusternode_t cttynode,
 		  int flag)
 {
+	if (!p->signal)
+		return 0;
+
+#ifndef PPROC_SETCTTY_SIGLOCK
+	/* SSI_XXX: deadlock
+	 * tasklist_lock	(pproc_psignal)
+	 * t->sighand->siglock	(pproc_psignal)
+	 *			(handle_stop_signal)
+	 *			(do_notify_parent)
+	 * FLAG LOCK		(vpop_report_state)
+	 *
+	 * FLAG LOCK		(pvpop_setsid, pvpop_setctty)
+	 * tasklist_lock	(pproc_setctty)
+	 * task_lock		(pproc_setctty)
+	 */
+#endif
 	read_lock(&tasklist_lock);
 	if (p->signal) {
 #ifdef PPROC_SETCTTY_SIGLOCK
 		SSI_ASSERT((flag & (VCTTY_SETCTTY|VCTTY_CLEARCTTY)) !=
 					(VCTTY_SETCTTY|VCTTY_CLEARCTTY));
-		/* SSI: Caller should have FLAG LOCK */
-		/* SSI_XXX: do the assert */
-#else
-		/* SSI_XXX: task_lock() doesn't protect ->signal */
-		task_lock(p);
 #endif
+		task_lock(p);
 		if (flag & VCTTY_SETCTTY) {
 			SSI_ASSERT(cttydev != NODEV);
 			p->signal->cttydev = cttydev;
@@ -136,9 +149,7 @@
 				p->signal->tty_old_pgrp = 0;
 			}
 		}
-#ifndef PPROC_SETCTTY_SIGLOCK
 		task_unlock(p);
-#endif
 	}
 	read_unlock(&tasklist_lock);
 
@@ -154,22 +165,20 @@
  * Calling/Exit State:
  *	None.
  */
+/* Called with VPROC_HOLD_MOVEMENT */
 int pproc_getctty(struct task_struct *p, dev_t *cttydev, clusternode_t *cttynode)
 {
+	if (!p->signal)
+		return 0;
+
 	read_lock(&tasklist_lock);
 	if (p->signal) {
-#ifdef PPROC_SETCTTY_SIGLOCK
-		/* SSI: Caller should have FLAG LOCK */
-#else
 		task_lock(p);
-#endif
 		if (cttydev)
 			*cttydev = p->signal->cttydev;
 		if (cttynode)
 			*cttynode = p->signal->cttynode;
-#ifndef PPROC_SETCTTY_SIGLOCK
 		task_unlock(p);
-#endif
 	}
 	read_unlock(&tasklist_lock);
 

Index: dvp_move.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/vproc/dvp_move.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- dvp_move.c	19 Feb 2009 08:01:02 -0000	1.14
+++ dvp_move.c	27 Oct 2009 03:18:29 -0000	1.15
@@ -35,8 +35,12 @@
 #include <cluster/gen/ics_vproc_macros_gen.h>
 #include <cluster/gen/ics_vproc_protos_gen.h>
 
-struct list_head movement_list = LIST_HEAD_INIT(movement_list);
-DEFINE_SPINLOCK(movement_list_lock);
+static LIST_HEAD(movement_list);
+static __cacheline_aligned_in_smp DEFINE_SPINLOCK(movement_list_lock);
+/* Lock ordering:
+ *	movement_list_lock
+ *	mh_lock
+ */
[...1174 lines suppressed...]
+		else
+			move_in_continue(h, 1);
+		put_move_header(h);
+	}
+
+	kfree(down_list);
+#else
 	struct move_header *h, *next;
 	LIST_HEAD(down_list);
 
@@ -1780,7 +2067,9 @@
 			move_out_nodedown(h);
 		else
 			move_in_continue(h, 1);
+		put_move_header(h);
 	}
+#endif /* !VPROC_RCU_MOVEMENT_LIST */
 }
 
 void

Index: rproc_server.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/vproc/rproc_server.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- rproc_server.c	10 Oct 2008 08:10:32 -0000	1.9
+++ rproc_server.c	27 Oct 2009 03:18:30 -0000	1.10
@@ -199,8 +199,7 @@
 svrproc_handle_children(void)
 {
 #ifndef VPROC_PVP_CHILD_LL
-	struct task_struct *t = current;
-	struct vproc *vp = t->p_vproc;
+	struct vproc *vp = current->p_vproc;
 	struct pvproc *pvp = PVP(vp);
 #else
 	struct vproc *vp = current->p_vproc;
@@ -220,7 +219,6 @@
 	while ((vc = pvp->pvp_head_childl) != NULL) {
 		VPROC_LOCK_ND_LIST_EXCL(vp, __FUNCTION__);
 		pvp->pvp_head_childl = PVP(vc)->pvp_childl;
-		mb();
 		PVP(vc)->pvp_childl = NULL;
 		VPROC_UNLOCK_ND_LIST_EXCL(vp, __FUNCTION__);
 #endif /* !VPROC_PVP_CHILD_LL */

Index: dvp_pvpops.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/vproc/dvp_pvpops.c,v
retrieving revision 1.40
retrieving revision 1.41
diff -u -d -r1.40 -r1.41
--- dvp_pvpops.c	24 Mar 2009 04:26:28 -0000	1.40
+++ dvp_pvpops.c	27 Oct 2009 03:18:29 -0000	1.41
@@ -294,8 +294,7 @@
 	/* Need to check if correct state otherwise return EAGAIN */
 	VPROC_LOCK_FLAG(v, "pvpop_reap");
 #ifdef VPROC_CONTINUE
-	if (!(pvp->pvp_wstate & (PVWS_SZOMB | PVWS_SSTOP
-				 | PVWS_STRAP | PVWS_SUNSTOP))) {
+	if (pvp->pvp_wstate < PVWS_SSTOP || pvp->pvp_wstate > PVWS_SZOMB) {
 #else
 	if ((pvp->pvp_wstate != PVWS_SZOMB) && (pvp->pvp_wstate != PVWS_SSTOP)
 					&& (pvp->pvp_wstate != PVWS_STRAP)){
@@ -330,7 +329,7 @@
 		goto out;
 	}
 
-#ifdef VPROC_VPROC_WNOTHREAD
+#ifdef VPROC_VPROC_WNOTHREAD__NOTUSED
 	/*
 	 * Do not consider detached threads that are
 	 * not ptraced:
@@ -405,7 +404,9 @@
 			 */
 			if (origin_node == CLUSTERNODE_INVAL &&
 							!PIDNODE(v->vp_pid)) {
+				VPROC_LOCK_FLAG(v, "pvpop_reap");
 				pvp->pvp_flag &= ~PV_PROC_ORIGIN;
+				VPROC_UNLOCK_FLAG(v, "pvpop_reap");
 				VPROC_RELE(v, "pvpop_reap(origin)");
 				break;
 			}
@@ -435,7 +436,11 @@
 
 		/* Resign from the pgrp */
 		if (pvp->pvp_pgid != 0) {
+#ifdef VPROC_RELEASE__REFCNT_RACE_FIX
+			struct vproc *g = VPROCPTR_NOHOLD(pvp->pvp_pgid);
+#else
 			register struct vproc *g = VPROCPTR(pvp->pvp_pgid);
+#endif
 /*
 #ifdef VPROC_DEBUG
 			printk("pvpop_reap: resigning from pgrp %d\n",
@@ -450,9 +455,6 @@
 							       FALSE);
 #endif
 			VPROC_RELE(g, "pvpop_reap(pgrp ldr on member node)");
-#ifdef VPROC_RELEASE__REFCNT_RACE_FIX
-			VPROC_RELE(g, "pvpop_reap(vprocptr g)");
-#endif
 		}
 
 		VPROC_RELE_PID(pvp->pvp_ppid,
@@ -607,8 +609,13 @@
 	 * Add child to its new parent's parent-sibling-child list
 	 */
 	 if (!held) {
+#ifdef TASK_HOLD_VPROC
+		if (pp->vp_pid != 1 &&
+		    (PVP(v)->pvp_flag & PV_IS_LOCAL) && PVP(v)->pvp_pproc->ptrace) {
+#else
 		if (pp->vp_pid != 1 &&
 		    PVP(v)->pvp_pproc && PVP(v)->pvp_pproc->ptrace) {
+#endif
 			if (!(TRY_VPROC_LOCK_EXCL(pp, 
 					"pvpop_add_child_to_parent(parent)"))) {
 				error = -EAGAIN;
@@ -653,7 +660,6 @@
 	VPROC_ADD_PARENT(v, pp);
 #else
 	PVP(v)->pvp_childl = PVP(pp)->pvp_head_childl;
-	mb();
 	PVP(pp)->pvp_head_childl = v;
 #endif /* !VPROC_PVP_CHILD_LL */
 	VPROC_UNLOCK_ND_LIST_EXCL(pp, "pvpop_add_child_to_parent(child)");
@@ -750,6 +756,13 @@
 			idelay(HZ/10);
 			if (count++ < 10)
 				continue;
+			if (PVP(v)->pvp_wstate == PVWS_SZOMB) {
+				/* Remote __ptrace_unlink() deadlocked with local
+				 * pvpop_wait() when remote child is ptraced.
+				 */
+				/* We rely on ND LIST LOCK */
+				break;
+			}
 			printk(KERN_WARNING "%s: waiting for parent lock %d\n",
 				__FUNCTION__, pp->vp_pid);
 			count = 0;
@@ -793,7 +806,6 @@
 	VPROC_LOCK_ND_LIST_EXCL(pp, "pvpop_rmv_child_from_parent(parent)");
 	if (PVP(pp)->pvp_head_childl == v) {
 		PVP(pp)->pvp_head_childl = PVP(v)->pvp_childl;
-		mb();
 		PVP(v)->pvp_childl = NULL;
 	}
 	else {
@@ -812,7 +824,6 @@
 		}
 
 		PVP(w)->pvp_childl = PVP(v)->pvp_childl;
-		mb();
 		PVP(v)->pvp_childl = NULL;
 	}
 	VPROC_UNLOCK_ND_LIST_EXCL(pp, "pvpop_rmv_child_from_parent(parent)");
@@ -895,6 +906,10 @@
 
 	if (!RPVPOP_IS_LOCAL(&rargs)) {
 		VPROC_RELEASE_MOVEMENT(v, "pvpop_reassign_child");
+#ifdef VPROC_RELEASE__REFCNT_RACE_FIX
+		if (vi)
+			VPROC_RELE(vi, "temp pvpop_reassign_child(init)");
+#endif
 		return(error);
 	}
 
@@ -902,8 +917,6 @@
 	 * Perform operation locally.
 	 */
 retry:
-	VPROC_LOCK_EXCL(v, "pvpop_reassign_child");
-
 #ifdef CONFIG_VPROC_ND
 	/*
 	 * If the process has already been reaped, we return without
@@ -912,7 +925,16 @@
 	 */
 #ifdef VPROC_HOLD_ZERO_GET_TASK
 	if (!PV_IS_ALIVE(pvp)) {
+		error = -ESRCH;
+		goto out_nolock;
+	}
+
+	VPROC_LOCK_EXCL(v, "pvpop_reassign_child");
+
+	if (!PV_IS_ALIVE(pvp)) {
 #else
+	VPROC_LOCK_EXCL(v, "pvpop_reassign_child");
+
 	if (pvp->pvp_pproc == NULL) {
 #endif
 		error = -ESRCH;
@@ -1011,7 +1033,11 @@
 		dpvproc_change_parent_child_care(pvp->pvp_ppid, vi->vp_pid, v->vp_pid, FALSE);
 #endif /* VPROC_ND */
 
+#ifdef VPROC_RELEASE__REFCNT_RACE_FIX
+	vp = VPROCPTR_NOHOLD(pvp->pvp_ppid);
+#else
 	vp = VPROCPTR(pvp->pvp_ppid);
+#endif
 	pvp->pvp_ppid = vi->vp_pid;
 
 	pproc_setattr(pvp->pvp_pproc, 0, 0, &pvp->pvp_ppid, 0, 0, 0);
@@ -1037,9 +1063,6 @@
 
 	/* release the former parent vproc on the child's node */
 	VPROC_RELE(vp, "pvpop_reassign_child(parent on child node");
-#ifdef VPROC_RELEASE__REFCNT_RACE_FIX
-	VPROC_RELE(vp, "temp pvpop_reassign_child(parent on child node)");
-#endif
 
 	/*
 	 * Do special processing on child node if parent exits
@@ -1059,7 +1082,6 @@
 				pvp->pvp_pproc->ptrace = 0;
 				wake_up_process(pvp->pvp_pproc);
 				do_notify_parent(pvp->pvp_pproc, 0, 0, 0);
-
 			}
 
 			(void) PVPOP_SIGPROC(v, SIGKILL, 0, NULL,
@@ -1074,6 +1096,9 @@
 
 out:
 	VPROC_UNLOCK_EXCL(v, "pvpop_reassign_child");
+#ifdef VPROC_HOLD_ZERO_GET_TASK
+out_nolock:
+#endif
 	VPROC_RELEASE_MOVEMENT(v, "pvpop_reassign_child");
 #ifdef VPROC_RELEASE__REFCNT_RACE_FIX
 	if (vi)
@@ -1099,8 +1124,7 @@
 	int rforkpt)		/* special case for rfork ptrace */
 {
 	struct pvproc *pvp = PVP(v);
-	struct vproc *vi = VPROCPTR(1);
-	struct vproc *vp;
+	struct vproc *vi, *vp = NULL;
 	struct rpvpop_args rargs;
 	int wstate, waited;
 	int error = 0;
@@ -1127,18 +1151,22 @@
 	RPVPOP_END_OP(&rargs, ret, error);
 
 	if (!RPVPOP_IS_LOCAL(&rargs)) {
-#ifdef VPROC_RELEASE__REFCNT_RACE_FIX
-		if (vi)
-			VPROC_RELE(vi, "pvpop_reclaim_child vprocptr vi");
-#endif
 		VPROC_RELEASE_MOVEMENT(v, "pvpop_reclaim_child");
 		return(error);
 	}
 
+	vi = VPROCPTR(1);
 retry:
 	/*
 	 * Perform operation locally.
 	 */
+#ifdef VPROC_HOLD_ZERO_GET_TASK
+	if (!PV_IS_ALIVE(pvp)) {
+		error = -ESRCH;
+		goto out_nolock;
+	}
+#endif
+
 #ifdef VPROC_RW_LOCK
 	if (!held) {
 		if (exlock)
@@ -1210,7 +1238,7 @@
 		goto skip_remove;
 
 	/* We could be remote so check even when client says islocked */
-	/* SSI_XXX: get rid of unused arg islocked */
+	/* TODO: get rid of unused arg islocked */
 	pp_held = VPROC_LOCK_EXCL_HELD(vi);
 	if (!pp_held) {
 #endif
@@ -1278,7 +1306,7 @@
 
 	vp = LOCATE_VPROC_PID(ppid, "pvpop_reclaim_child(parent at child)");
 	if (vp == NULL) {
-		printk("pvpop_child_reclaim: new parent doesn't exist!\n");
+		printk("pvpop_reclaim_child: new parent doesn't exist!\n");
 		error = -ENOENT;
 		goto out;
 	}
@@ -1293,11 +1321,10 @@
 #ifndef VPROC_RELEASE__REFCNT_RACE_FIX
 		VPROC_RELE(vp, "pvpop_child_reclaim");
 #endif
-
 		/* ptrace processes need to be assign to init if original parent dies */
 		if (pvp->pvp_pproc->ptrace) {
 #ifdef VPROC_RELEASE__REFCNT_RACE_FIX
-			VPROC_RELE(vp, "pvpop_child_reclaim");
+			VPROC_RELE(vp, "pvpop_reclaim_child");
 #endif
 			vp = LOCATE_VPROC_PID(1,"pvpop_reclaim_child(parent at child)");
 			error = PVPOP_ADD_CHILD_TO_PARENT(vp, v, wstate, waited);
@@ -1305,7 +1332,7 @@
 		}
 		if (error) {
 #ifdef VPROC_RELEASE__REFCNT_RACE_FIX
-			VPROC_RELE(vp, "pvpop_child_reclaim");
+			VPROC_RELE(vp, "pvpop_reclaim_child");
 #endif
 			printk("pvpop_child_reclaim: failed to add child to parent\n");
 			goto out;
@@ -1341,6 +1368,9 @@
 	if (!held)
 		VPROC_UNLOCK_EXCL(v, "pvpop_reclaim_child");
 #endif
+#ifdef VPROC_HOLD_ZERO_GET_TASK
+out_nolock:
+#endif
 	VPROC_RELEASE_MOVEMENT(v, "pvpop_reclaim_child");
 #ifdef VPROC_RELEASE__REFCNT_RACE_FIX
 	if (vi)
@@ -1521,7 +1551,11 @@
 
 		/* resign from current group */
 		if (pvp->pvp_pgid != 0) {
+#ifdef VPROC_RELEASE__REFCNT_RACE_FIX
+			struct vproc *og = VPROCPTR_NOHOLD(pvp->pvp_pgid);
+#else
 			register struct vproc *og = VPROCPTR(pvp->pvp_pgid);
+#endif
 			(void) PVPOP_RMV_PGRP_LIST(og, v, pvp->pvp_ppid, 0);
 #ifdef CONFIG_VPROC_ND
 			dpvproc_remove_pgrp_leader_member_care(og->vp_pid,
@@ -1529,9 +1563,6 @@
 							       FALSE);
 #endif
 			VPROC_RELE(og, "dvpop_setpgid(old pgrp ldr on mem node)");
-#ifdef VPROC_RELEASE__REFCNT_RACE_FIX
-			VPROC_RELE(og, "dvpop_setpgid(vprocptr og)");
-#endif
 		}
 
 		/*
@@ -1682,10 +1713,16 @@
 	/*
 	 * Perform operation locally.
 	 */
+#ifdef PPROC_SETCTTY_SIGLOCK
+	lock_kernel(); /* protect tty_old_pgrp. see disassociate_ctty() */
+#endif
 	VPROC_LOCK_EXCL(v, "pvpop_setsid");
 
 	if (unlikely(pvp->pvp_pgid == v->vp_pid ||
 		     pvp->pvp_flag & PV_PGRPLEADER)) {
+#ifdef PPROC_SETCTTY_SIGLOCK
+		unlock_kernel();
+#endif
 		error = -EPERM;
 		goto out;
 	}
@@ -1696,16 +1733,17 @@
 
 	/* resign from current process group */
 	if (pvp->pvp_pgid != 0) {
+#ifdef VPROC_RELEASE__REFCNT_RACE_FIX
+		struct vproc *g = VPROCPTR_NOHOLD(pvp->pvp_pgid);
+#else
 		register struct vproc *g = VPROCPTR(pvp->pvp_pgid);
+#endif
 		PVPOP_RMV_PGRP_LIST(g, v, pvp->pvp_ppid, 0);
 #ifdef CONFIG_VPROC_ND
 		dpvproc_remove_pgrp_leader_member_care(g->vp_pid, v->vp_pid,
 						       FALSE);
 #endif
 		VPROC_RELE(g, "pvpop_setsid(old pgrp leader on member node)");
-#ifdef VPROC_RELEASE__REFCNT_RACE_FIX
-		VPROC_RELE(g, "dvpop_setsid(vprocptr g)");
-#endif
 	}
 
 	VPROC_LOCK_SESSION_LIST_EXCL(v, "pvpop_setsid");
@@ -1746,9 +1784,17 @@
 	pvp->pvp_flag &= ~PV_SCTTY;
 	pvp->pvp_cttynode = CLUSTERNODE_INVAL;
 	pvp->pvp_cttydev = NODEV;
+#ifndef PPROC_SETCTTY_SIGLOCK
 	pproc_setctty(pvp->pvp_pproc, 0, 0, VCTTY_CLEARCTTY|VCTTY_SETLDR);
+#endif
 	pvp->pvp_flag |= (PV_PGRPLEADER | PV_SESSIONLEADER | PV_LDR_IN_SESS);
 	VPROC_UNLOCK_FLAG(v, "pvpop_setsid");
+#ifdef PPROC_SETCTTY_SIGLOCK
+	pproc_setctty(pvp->pvp_pproc, 0, 0, VCTTY_CLEARCTTY|VCTTY_SETLDR);
+	unlock_kernel();
+#endif
+
+	VPROC_UNLOCK_PGRP_LIST_EXCL(v, "pvpop_setsid");
 
 	/*
 	 * Place a pgrp leader and a session leader hold on the vproc
@@ -1765,9 +1811,7 @@
 			VPROC_REMOTE_RETRY_DELAY();
 	} while(ret == -EREMOTE);
 
-	VPROC_UNLOCK_PGRP_LIST_EXCL(v, "pvpop_setsid");
 	VPROC_UNLOCK_SESSION_LIST_EXCL(v, "pvpop_setsid");
-
 out:
 	VPROC_UNLOCK_EXCL(v, "pvpop_setsid");
 	VPROC_RELEASE_MOVEMENT(v, "pvpop_setsid");
@@ -1894,6 +1938,31 @@
 	 * Perform operation locally.
 	 */
 
+	/*
+	 * SSI_XXX: possible deadlock with signalling process.
+	 *	This happens when process is group leader.
+	 *
+	 * EX pvp_pgrp_list_lock	(pvpop_adjust_job_control_count)
+	 *				(pvpop_sigproc)
+	 *				(pproc_psignal)
+	 * EX pvp_generic_lock		(vpop_report_state)
+	 *
+	 * === OR ===
+	 *				(sys_kill)
+	 *				...
+	 * SHR pvp_pgrp_list_lock	(pvpop_sigpgrp)
+	 *				(pvpop_sigproc)
+	 *				(pproc_psignal)
+	 * EX pvp_generic_lock		(vpop_report_state)
+	 *
+	 * while we are in the following path:
+	 *				(do_fork)
+	 *				...
+	 * EX pvp_generic_lock		(vpop_setup_vproc_relations)
+	 *				(dvp_child_join_pgrp_end)
+	 * EX pvp_pgrp_list_lock	(pvpop_add_pgrp_list)
+	 */
+	/* Fixed with async vpop_report_state(). -RT */
 	VPROC_LOCK_PGRP_LIST_EXCL(g, "pvpop_add_pgrp_list");
 
 	if (!(PVP(g)->pvp_flag&PV_PGRPLEADER)) {
@@ -1906,11 +1975,9 @@
 			error = -EAGAIN;
 			goto out;
 		}
-		printk("pvpop_add_pgrp_list: member seqno > leader (%d > %d)!",
-		       *seqnop, PVP(g)->pvp_pgrp_ldr_seqno);
-#ifndef PVPOP_ADD_PGRP_LIST_NO_LEADER /* FIXME: Can hang VPROC due to lost leader? */
+		printk(KERN_CRIT "%s: member seqno > leader (%d > %d)!\n",
+		       __FUNCTION__, *seqnop, PVP(g)->pvp_pgrp_ldr_seqno);
 		PVP(g)->pvp_pgrp_ldr_seqno = *seqnop;
-#endif
 	}
 
 #ifdef CONFIG_VPROC_ND
@@ -1927,7 +1994,6 @@
 #endif
 
 	PVP(v)->pvp_pgrpl = PVP(g)->pvp_head_pgrpl;
-	mb();
 	PVP(g)->pvp_head_pgrpl = v;
 	VPROC_HOLD(g, "pvpop_add_pgrp_list(leader on leader node)");
 	VPROC_HOLD(v, "pvpop_add_pgrp_list(member on leader node)");
@@ -1994,8 +2060,8 @@
 	 * Perform operation locally.
 	 */
 
-	if (!TRY_VPROC_LOCK_PGRP_LIST_EXCL(g, "pvpop_rmv_pgrp_list")) {
-		if (async) {
+	if (async) {
+		if (!TRY_VPROC_LOCK_PGRP_LIST_EXCL(g, "pvpop_rmv_pgrp_list")) {
 			/* Need to queue up rmv to async daemon to avoid 
 			 * deadlocking the reaping parent
 			 */
@@ -2003,8 +2069,8 @@
 			error = -EBUSY;
 			goto out;
 		}
+	} else
 		VPROC_LOCK_PGRP_LIST_EXCL(g, "pvpop_rmv_pgrp_list");
-	}
 
 	if (!(PVP(g)->pvp_flag&PV_PGRPLEADER)) {
 /* #ifdef DEBUG
@@ -2022,7 +2088,6 @@
 #endif DEBUG */
 		/* v is the first in the list */
 		PVP(g)->pvp_head_pgrpl = PVP(v)->pvp_pgrpl;
-		mb();
 		PVP(v)->pvp_pgrpl = NULL;
 	}
 	else {
@@ -2044,7 +2109,6 @@
 		}
 
 		PVP(w)->pvp_pgrpl = PVP(v)->pvp_pgrpl;
-		mb();
 		PVP(v)->pvp_pgrpl = NULL;
 /* #ifdef DEBUG
 		printk("pvpop_rmv_pgrp_list: linked pgrpl for %d to %d\n",
@@ -2072,7 +2136,11 @@
 
 		/* no more process group - resign from session too */
 		if (PVP(g)->pvp_sid != 0) {
+#ifdef VPROC_RELEASE__REFCNT_RACE_FIX
+			s = VPROCPTR_NOHOLD(PVP(g)->pvp_sid);
+#else
 			s = VPROCPTR(PVP(g)->pvp_sid);
+#endif
 			PVPOP_RMV_SESSION_LIST(s, g);
 #ifdef CONFIG_VPROC_ND
 			if (s != g) {
@@ -2083,9 +2151,6 @@
 			}
 #endif
 			VPROC_RELE(s, "pvpop_rmv_pgrp_list(session on member node)");
-#ifdef VPROC_RELEASE__REFCNT_RACE_FIX
-			VPROC_RELE(s, "pvpop_rmv_pgrp_list(vprocptr s)");
-#endif
 		}
 		/*
 		 * Release a hold on the pgrp leader's origin node vproc.
@@ -2211,7 +2276,6 @@
 
 		/* insert g at the head to the session list */
 		PVP(g)->pvp_sessionl = PVP(s)->pvp_sessionl;
-		mb();
 		PVP(s)->pvp_sessionl = g;
 	}
 
@@ -2293,7 +2357,6 @@
 		}
 
 		PVP(w)->pvp_sessionl = PVP(g)->pvp_sessionl;
-		mb();
 		PVP(g)->pvp_sessionl = NULL;
 	}
 	VPROC_UNLOCK_ND_LIST_EXCL(s, "pvpop_rmv_session_list");
@@ -2516,6 +2579,12 @@
 	/*
 	 * Perform operation locally.
 	 */
+#ifdef VPROC_HOLD_ZERO_GET_TASK
+	if (!PV_IS_ALIVE(PVP(v))) {
+		error = -ESRCH;
+		goto out;
+	}
+#endif
 
 	switch (flag) {
 	case VPROC_GET:
@@ -2529,6 +2598,9 @@
 		return(-EINVAL);
 	}
 
+#ifdef VPROC_HOLD_ZERO_GET_TASK
+out:
+#endif
 	VPROC_RELEASE_MOVEMENT(v, "pvpop_proc_nice");
 	return error;
 }
@@ -2974,7 +3046,11 @@
         PVP(g)->pvp_pgrp_ldr_seqno++;   /* bump ldr's seqno before members' */
 	VPROC_UNLOCK_FLAG(g, "pvpop_sigpgrp");
 
-	VPROC_LOCK_PGRP_LIST_SHARED(g, "pvpop_sigpgrp");
+	/* We must obtain EX lock here for deadlock detection in path:
+	 * PVPOP_SIGPROC, ..., VPOP_REPORT_STATE
+	 */
+	/* VPROC_LOCK_PGRP_LIST_SHARED(g, "pvpop_sigpgrp"); */
+	VPROC_LOCK_PGRP_LIST_EXCL(g, "pvpop_sigpgrp");
 	error = -ESRCH;
 	for (w = PVP(g)->pvp_head_pgrpl;
 			w != NULL;
@@ -2990,7 +3066,7 @@
 		if (error == ESUCCESS)
 			nsuccesses++;
 	}
-	VPROC_UNLOCK_PGRP_LIST_SHARED(g, "pvpop_sigpgrp");
+	VPROC_UNLOCK_PGRP_LIST_EXCL(g, "pvpop_sigpgrp");
 	VPROC_RELEASE_MOVEMENT(g, "pvpop_sigpgrp");
 
 	return(nsuccesses ? ESUCCESS : error);
@@ -3285,16 +3361,22 @@
 		return(-ESRCH);
 	}
 
+#ifdef PPROC_SETCTTY_SIGLOCK
+	lock_kernel(); /* protect tty_old_pgrp. see disassociate_ctty() */
+#endif
 	if (pgid > 0  && (pvp->pvp_flag & PV_SESSIONLEADER) &&
 						(flags & VCTTY_CLEARCTTY)) {
 		PVPOP_SIGPROC(v, SIGHUP, SIGCONT, 0, VSIG_INTERNAL, NULL);
 #ifdef VPROC_HOLD_ZERO_GET_TASK
 		if (PV_IS_ALIVE(pvp)) {
-			lock_kernel(); /* SSI_XXX: Linux tty under BKL */
-			read_lock(&tasklist_lock);
-			pvp->pvp_pproc->signal->tty_old_pgrp = pgid;
-			read_unlock(&tasklist_lock);
-			unlock_kernel();
+			task_t *p = pvp->pvp_pproc;
+#ifdef PPROC_SETCTTY_SIGLOCK
+			task_lock(p); /* see pproc_setctty() */
+#endif
+			p->signal->tty_old_pgrp = pgid;
+#ifdef PPROC_SETCTTY_SIGLOCK
+			task_unlock(p);
+#endif
 		}
 #else
 		if (PVP(v)->pvp_pproc != NULL)
@@ -3376,10 +3458,16 @@
 	if (flags & VCTTY_CLEARFGPGRP) {
 		pvp->pvp_flag &= ~PV_FGPGRP;
 	}
+#ifndef PPROC_SETCTTY_SIGLOCK
 	if (pvp->pvp_pproc != NULL) {
 		pproc_setctty(pvp->pvp_pproc,cttydev,cttynode,flags);
 	}
+#endif
 	VPROC_UNLOCK_FLAG(v, "pvpop_setctty");
+#ifdef PPROC_SETCTTY_SIGLOCK
+	if (pvp->pvp_pproc)
+		pproc_setctty(pvp->pvp_pproc,cttydev,cttynode,flags);
+#endif
 
 	if (do_me_as_pgrp_mem)
 		VPROC_UNLOCK_PGRP_LIST_SHARED(v, "pvpop_setctty");
@@ -3387,6 +3475,9 @@
 done:
 	if (setsessionlock)
 		VPROC_UNLOCK_SESSION_LIST_EXCL(v, "pvpop_setctty");
+#ifdef PPROC_SETCTTY_SIGLOCK
+	unlock_kernel();
+#endif
 	VPROC_RELEASE_MOVEMENT(v, "pvpop_setctty");
 	return 0;
 }
@@ -3434,9 +3525,11 @@
 	 * Perform operation locally.
 	 */
 
+	VPROC_LOCK_FLAG(v, "pvpop_setctty");
 	*cttydev = pvp->pvp_cttydev;
 	*cttynode = pvp->pvp_cttynode;
 	*is_fgpgrp = (pvp->pvp_flag & PV_FGPGRP);
+	VPROC_UNLOCK_FLAG(v, "pvpop_setctty");
 
 	VPROC_RELEASE_MOVEMENT(v, "pvpop_getctty");
 	return 0;
@@ -3621,6 +3714,13 @@
 	/*
 	 * Perform operation locally.
 	 */
+#ifdef VPROC_HOLD_ZERO_GET_TASK
+	if (!PV_IS_ALIVE(PVP(v))) {
+		printk(KERN_WARNING "%s: dead epid %d\n", __FUNCTION__, v->vp_pid);
+		error = -ESRCH;
+		goto out;
+	}
+#endif
 
 	/*
 	 * We check the caller's masks before re-directing the operation
@@ -3630,38 +3730,30 @@
 	pproc_chksigmask((struct task_struct *)PVP(v)->pvp_pproc, spid, signo, &is_masked,
 			 &is_ignored);
 	if (is_masked || is_ignored) {
-		VPROC_RELEASE_MOVEMENT(v, "pvpop_terminal_sigpgrp");
-		return(-EIO);
+		error = -EIO;
+		goto out;
 	}
 	if (flag & VSIG_CHECKGROUP) {
 		if (PVP(v)->pvp_pgid == 0) {
 			error = PVPOP_SIGPROC(v,signo,0,pinfo,(pinfo ? 0 : VSIG_INTERNAL),
 					      NULL);
-			VPROC_RELEASE_MOVEMENT(v, "pvpop_terminal_sigpgrp");
-			return(error);
+			goto out;
 		}
 	}
-	if (PVP(v)->pvp_pgid == 0) {
-		VPROC_RELEASE_MOVEMENT(v, "pvpop_terminal_sigpgrp");
-		return(0);
-	}
-	{
+	if (PVP(v)->pvp_pgid != 0) {
 		register struct vproc *g = VPROCPTR(PVP(v)->pvp_pgid);
 
 		if (flag & VSIG_NOORPHAN) {
 			error = PVPOP_SIGPGRP(g, signo, pinfo,
 					      (pinfo ? 0 : VSIG_INTERNAL)|VSIG_NOORPHAN, NULL);
-			VPROC_RELEASE_MOVEMENT(v, "pvpop_terminal_sigpgrp");
-#ifdef VPROC_RELEASE__REFCNT_RACE_FIX
-			VPROC_RELE(g, "pvpop_terminal_sigpgrp(vprocptr g)");
-#endif
-			return(error);
-		}
-		error = PVPOP_SIGPGRP(g, signo, pinfo, (pinfo ? 0 : VSIG_INTERNAL), NULL);
+		} else
+			error = PVPOP_SIGPGRP(g, signo, pinfo,
+					      (pinfo ? 0 : VSIG_INTERNAL), NULL);
 #ifdef VPROC_RELEASE__REFCNT_RACE_FIX
 		VPROC_RELE(g, "pvpop_terminal_sigpgrp(vprocptr g)");
 #endif
 	}
+out:
 	VPROC_RELEASE_MOVEMENT(v, "pvpop_terminal_sigpgrp");
 	return(error);
 }
@@ -3734,6 +3826,13 @@
 	/*
 	 * Perform operation locally
 	 */
+#ifdef VPROC_HOLD_ZERO_GET_TASK
+	if (!PV_IS_ALIVE(pvp)) {
+		printk(KERN_WARNING "%s: dead task %d\n", __FUNCTION__, v->vp_pid);
+		error = -ESRCH;
+		goto out;
+	}
+#endif
 
 	pidlocal = (v->vp_pid == lock_pid);
 	PVPSOP_CAPABILITY_LOCK_NODE(clms_master_node, lock_pid, pidlocal);
@@ -3749,6 +3848,9 @@
 	PVPSOP_CAPABILITY_UNLOCK_NODE(this_node, lock_pid, pidlocal);
 	PVPSOP_CAPABILITY_UNLOCK_NODE(clms_master_node, lock_pid, pidlocal);
 
+#ifdef VPROC_HOLD_ZERO_GET_TASK
+out:
+#endif
 	VPROC_RELEASE_MOVEMENT(v, "pvpop_capset_task");
 	return error;
 }
@@ -3821,6 +3923,13 @@
 	/*
 	 * Perform operation locally
 	 */
+#ifdef VPROC_HOLD_ZERO_GET_TASK
+	if (!PV_IS_ALIVE(pvp)) {
+		printk(KERN_WARNING "%s: dead task %d\n", __FUNCTION__, v->vp_pid);
+		error = -ESRCH;
+		goto out;
+	}
+#endif
 
 	pidlocal = (v->vp_pid == lock_pid);
 	PVPSOP_CAPABILITY_LOCK_NODE(this_node, lock_pid, pidlocal);
@@ -3833,6 +3942,9 @@
 	*inheritable = data.inheritable;
 	*permitted = data.permitted;
 
+#ifdef VPROC_HOLD_ZERO_GET_TASK
+out:
+#endif
 	VPROC_RELEASE_MOVEMENT(v, "pvpop_capget");
 	return error;
 }
@@ -3885,7 +3997,6 @@
 	VPROC_HOLD(vc, "pvpop_add_to_originalchild_list");
 	VPROC_LOCK_ND_LIST_EXCL(vp, "pvpop_add_to_originalchild_list");
 	PVP(vc)->pvp_oclist = PVP(vp)->pvp_head_oclist;
-	mb();
 	PVP(vp)->pvp_head_oclist = vc;
 	VPROC_UNLOCK_ND_LIST_EXCL(vp, "pvpop_add_to_originalchild_list");
 	PVP(vc)->pvp_oppid = vp->vp_pid;
@@ -3938,7 +4049,6 @@
 	VPROC_LOCK_ND_LIST_EXCL(vp, "pvpop_rmv_child_from_parent(parent)");
 	if (PVP(vp)->pvp_head_oclist == vc) {
 		PVP(vp)->pvp_head_oclist = PVP(vc)->pvp_oclist;
-		mb();
 		PVP(vc)->pvp_oclist = NULL;
 	}
 	else {
@@ -3954,7 +4064,6 @@
 		}
 
 		PVP(w)->pvp_oclist = PVP(vc)->pvp_oclist;
-		mb();
 		PVP(vc)->pvp_oclist = NULL;
 	}
 	VPROC_RELE(vc, "pvpop_rmv_to_originalchild_list");
@@ -3990,12 +4099,23 @@
 
 	usevp = newvp;
 	VPROC_LOCK_FLAG(usevp, "pvpop_reassign_original_parent");
+#ifdef VPROC_RELEASE__REFCNT_RACE_FIX
+	if (PVP(newvp)->pvp_wstate == PVWS_SZOMB) {
+		BUG_ON(pid == 1);
+		newvp = initvp;
+	} else
+		VPROC_HOLD(usevp, "pvpop_reassign_original_parent");
+
+	VPROC_UNLOCK_FLAG(usevp, "pvpop_reassign_original_parent");
+	VPROC_RELE(usevp, "pvpop_reassign_original_parent");
+#else
 	if (PVP(newvp)->pvp_wstate == PVWS_SZOMB)
 	{
 		VPROC_RELE(newvp, "pvpop_reassign_original_parent");
 		newvp = initvp;
 	}
 	VPROC_UNLOCK_FLAG(usevp, "pvpop_reassign_original_parent");
+#endif /* !VPROC_RELEASE__REFCNT_RACE_FIX */
 	SSI_ASSERT(pid == 2 || initvp != NULL);
 
 	VPROC_LOCK_EXCL(v, "pvpop_reassign_original_parent");
@@ -4016,11 +4136,12 @@
 		PVPOP_REASSIGN_CHILD(w, PV_ORIGP_EXIT);
 		VPROC_RELE(w, "pvpop_reassign_original_parent");
 	}
+	VPROC_UNLOCK_EXCL(v, "pvpop_reassign_original_parent");
 
-	VPROC_RELE(newvp, "pvpop_reassign_original_parent");
-	if (newvp != initvp && initvp != NULL)
+	if (newvp)
+		VPROC_RELE(newvp, "pvpop_reassign_original_parent");
+	if (initvp && newvp != initvp)
 		VPROC_RELE(initvp, "pvpop_reassign_original_parent");
-	VPROC_UNLOCK_EXCL(v, "pvpop_reassign_original_parent");
 	return 0;
 }
 
@@ -4324,7 +4445,6 @@
 	struct rpvpop_args rargs;
 	int ret, error;
 	ssi_procstate_t pstate;
-	struct task_struct *task = NULL;
 	ics_userbuf_t ubuf;
 
 	/*
@@ -4357,20 +4477,16 @@
 	/*
 	 * Perform operation locally.
 	 */
-	task = pvp->pvp_pproc;
 #ifdef VPROC_HOLD_ZERO_GET_TASK
-	WARN_ON(!task);
-#ifdef SSI_SKIP
 	if (!PV_IS_ALIVE(pvp)) {
 		error = -ESRCH;
 		goto out;
 	}
 #endif
-#endif
 	if (mem)
-		error = do_ssi_mem(task, buffer, count, ppos, type);
+		error = do_ssi_mem(pvp->pvp_pproc, buffer, count, ppos, type);
 	else
-		error = do_ssi_maps(task, buffer, count, ppos);
+		error = do_ssi_maps(pvp->pvp_pproc, buffer, count, ppos);
 
 out:
 	VPROC_RELEASE_MOVEMENT(v, "pvpop_proc_readmaps");
@@ -4617,7 +4733,7 @@
 	 */
 	error = -ESRCH;
 #ifdef VPROC_HOLD_ZERO_GET_TASK
-	if (pvp->pvp_flag & PV_EXITING)
+	if (!PV_IS_ALIVE(pvp) || (pvp->pvp_pproc->flags & PF_EXITING))
 		goto out;
 #else
 #ifdef VPROC_RW_LOCK

Index: rproc_cli_pproc.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/vproc/rproc_cli_pproc.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- rproc_cli_pproc.c	19 Feb 2009 08:01:02 -0000	1.22
+++ rproc_cli_pproc.c	27 Oct 2009 03:18:30 -0000	1.23
@@ -86,7 +86,9 @@
 	rsqp = &rsp->rvp_sp_queue;
 	SSI_ASSERT(!rsqp->rvp_sigqueue_t_val);
 	SSI_ASSERT(!rsqp->rvp_sigqueue_t_len);
+
 	spin_lock_irqsave(&t->sighand->siglock, flags);
+
 	list_for_each(lp, &sp->list)
 		rsqp->rvp_sigqueue_t_len++;
 	spin_unlock_irqrestore(&t->sighand->siglock, flags);
@@ -101,6 +103,7 @@
 	return 0;
 }
 
+/* Caller holds task->sighand->siglock */
 static int
 load_rvp_sigpending(struct sigpending *sp, rvp_sigpending_t *rsp)
 {
@@ -156,7 +159,9 @@
 				sigpending_remove_msg(rsp);
 				return -ENOMEM;
 			}
+
 			spin_lock_irqsave(&t->sighand->siglock, flags);
+
 			error |= load_rvp_sigpending(sp, rsp);
 			sp = &t->pending;
 			rsp = &comm_datap->comm_pending;
@@ -164,12 +169,14 @@
 			if (!error)
 				break;
 			spin_unlock_irqrestore(&t->sighand->siglock, flags);
+
 			sigpending_remove_msg(rsp);
 			rsp = &comm_datap->comm_signal.rvp_ss_shared_pending;
 			sigpending_remove_msg(rsp);
 		}
 	} else
 		spin_lock_irqsave(&current->sighand->siglock, flags);
+
 	comm_datap->comm_signal.rvp_ss_flags = t->signal->flags;
 	comm_datap->comm_signal.rvp_ss_tty_old_pgrp = t->signal->tty_old_pgrp;
 	comm_datap->comm_signal.rvp_ss_leader = t->signal->leader;
@@ -191,6 +198,7 @@
 	array_cpy(comm_datap->comm_sigaction, t->sighand->action);
 	comm_datap->comm_blocked = t->blocked;
 	comm_datap->comm_real_blocked = t->real_blocked;
+
 	spin_unlock_irqrestore(&t->sighand->siglock, flags);
 
 	return 0;
@@ -493,12 +501,12 @@
 #endif
 						&comm_datap->comm_p_cdir);
 out:
-	mntput(rootmnt);
-	dput(root);
-	mntput(altrootmnt);
-	dput(altroot);
-	mntput(pwdmnt);
 	dput(pwd);
+	mntput(pwdmnt);
+	dput(altroot);
+	mntput(altrootmnt);
+	dput(root);
+	mntput(rootmnt);
 
 	return error;
 }
@@ -539,6 +547,7 @@
 	}
 	comm_datap->comm_flags = t->flags;
 	comm_datap->comm_ptrace = t->ptrace;
+
 	rq = task_rq_lock(t, &flags);
 	comm_datap->comm_prio = t->prio;
 	comm_datap->comm_static_prio = t->static_prio;
@@ -546,6 +555,7 @@
 	comm_datap->comm_policy = t->policy;
 	comm_datap->comm_rt_priority = t->rt_priority;
 	task_rq_unlock(rq, &flags);
+
 	comm_datap->comm_exit_code = t->exit_code;
 	comm_datap->comm_exit_signal = t->exit_signal;
 #ifdef VPROC_UNLOAD_SETSCHED_SMP
@@ -602,8 +612,11 @@
 
 	array_cpy(comm_datap->comm_comm, t->comm);
 
-	if (!RVP_ISRFORK(optype))
-		semundo_load_msg(&comm_datap->comm_sysvsem);
+	if (!RVP_ISRFORK(optype)) {
+		error = semundo_load_msg(&comm_datap->comm_sysvsem);
+		if (error)
+			goto out;
+	}
 
 /* SSI_XXX: we have a race with anyone who changes the root/cwd
  * of multiple tasks at once (such as pivot_root)
@@ -844,6 +857,7 @@
 	noncfs_locks = 0;
 	files = task->files;
 	if (files) {
+		lock_kernel(); /* for i_flock list */
 		spin_lock(&files->file_lock);
 		for(i=0; i < files->max_fds; i++) {
 			struct file_lock *fl;
@@ -862,6 +876,7 @@
 			}
 		}
 		spin_unlock(&files->file_lock);
+		unlock_kernel();
 	}
 
 	return noncfs_locks;
@@ -973,6 +988,16 @@
 			goto out;
 		}
 
+#ifdef VPROC_MIGRATE_THREAD_GROUP_FIX
+		if (t->sysvsem.undo_list &&
+		    (atomic_read(&(t->sysvsem.undo_list)->refcnt) > 1)) {
+			error = -EBUSY;
+			printk(KERN_DEBUG "Cannot move process %d - "
+			       "%s has CLONE_SYSVSEM\n",
+			       t->pid, t->comm);
+			goto out;
+		}
+#endif
 	}
 
 	/*
@@ -1008,6 +1033,7 @@
 		goto out;
 	}
 
+#ifndef VPROC_MIGRATE_THREAD_GROUP_FIX
 	if (t->sysvsem.undo_list &&
 	    (atomic_read(&(t->sysvsem.undo_list)->refcnt) > 1)) {
 		error = -EBUSY;
@@ -1016,6 +1042,7 @@
 		       t->pid, t->comm);
 		goto out;
 	}
+#endif
 
 	if (t->mm->def_flags != 0) {
 		error = -EBUSY;

Index: nd_origin.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/vproc/nd_origin.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- nd_origin.c	24 Mar 2009 04:26:28 -0000	1.11
+++ nd_origin.c	27 Oct 2009 03:18:30 -0000	1.12
@@ -32,7 +32,7 @@
 
 
 #ifdef RCU_VPROC_ORIGIN_LIST
-spinlock_t vproc_origin_list_lock;
+static __cacheline_aligned_in_smp DEFINE_SPINLOCK(vproc_origin_list_lock);
 #else
 RW_LOCK_T vproc_origin_list_lock;
 #endif
@@ -49,7 +49,7 @@
 SSI_ASSERT_ONLY_DECL(static int vproc_check_care_rmv = 0);
 
 CONDITION_T vproc_origin_create_cond;
-COND_LOCK_T vproc_origin_create_mutex;
+COND_LOCK_T vproc_origin_create_mutex __cacheline_aligned_in_smp;
 
 
 static void vproc_origin_setup_groups(vproc_origin_data_t *, clusternode_t);
@@ -61,9 +61,7 @@
  */
 void vproc_origin_list_init(void)
 {
-#ifdef RCU_VPROC_ORIGIN_LIST
-	spin_lock_init(&vproc_origin_list_lock);
-#else
+#ifndef RCU_VPROC_ORIGIN_LIST
 	INIT_RW_LOCK(&vproc_origin_list_lock);
 #endif
 #ifdef SSI_NOTUSED
@@ -296,9 +294,8 @@
 #ifndef VPROC_LOCKING_CONTEXT_FIX
 	/* Wait for lookups that won the race to obtain shared vod_rwlock */
 #endif
-	/* NB: expect zero vod_refcnt most of the time */
 	while (atomic_read(&vodp->vod_refcnt))
-		idelay(HZ/10);
+		nidelay(HZ/20);
 #endif /* RCU_VPROC_ORIGIN_LIST */
 
 #ifndef VPROC_LOCKING_CONTEXT_FIX
@@ -473,6 +470,7 @@
 #endif
 }
 
+/* Called with vod_carehash_rwlock or vod_carequeue_mutex held */
 static void
 vproc_origin_care_list_add(
 	vproc_carehead_t	**vchlistpp,
@@ -533,6 +531,7 @@
 	vproc_caredata_add(vchp, vcdnew);
 }
 
+/* Called with vod_carehash_rwlock or vod_carequeue_mutex held */
 static void
 vproc_origin_care_list_remove(
 	vproc_carehead_t	**vchlistpp,
@@ -818,14 +817,14 @@
 	nsc_nodelist_t *nodelist)
 {
 	vproc_origin_data_t *vodp;
+	nsc_nodelist_t *nl = NSC_NODELIST_COPY(nodelist);
 
 	vodp = vproc_origin_find(this_node);
 	SSI_ASSERT(vodp != NULL);
 
-	nodelist = NSC_NODELIST_COPY(nodelist);
 	LOCK_COND_LOCK(&vodp->vod_response_mutex);
-	vodp->vod_nodelist = nodelist;
-	vodp->vod_numnodes = NSC_NODELIST_COUNT(nodelist);
+	vodp->vod_nodelist = nl;
+	vodp->vod_numnodes = NSC_NODELIST_COUNT(nl);
 	UNLOCK_COND_LOCK(&vodp->vod_response_mutex);
 
 	/*
@@ -913,7 +912,7 @@
 	 */
 #ifdef VPROC_LOCKING_CONTEXT_FIX
 #ifndef RCU_VPROC_ORIGIN_LIST
-#warning not supported
+#error not supported
 #endif
 	LOCK_COND_LOCK(&vproc_origin_create_mutex);
 	while (!(vodp = vproc_origin_find_nolock(trans_node))) {

Index: procfs_mount.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/vproc/procfs_mount.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- procfs_mount.c	24 Mar 2009 04:26:28 -0000	1.12
+++ procfs_mount.c	27 Oct 2009 03:18:30 -0000	1.13
@@ -134,6 +134,7 @@
 			BUG();
 		}
 	}
+	NSC_NODELIST_FREE(nl);
 	free_page(page);
 	return 0;
 }
@@ -258,6 +259,7 @@
 		if (rval)
 			BUG();
 	}
+	NSC_NODELIST_FREE(nl);
 	ssi_put_mntid(mnt);
 	return 0;
 
@@ -285,6 +287,7 @@
 		if (rval)
 			BUG();
 	}
+	NSC_NODELIST_FREE(nl);
 	return error;
 }
 

Index: vp_debug.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/vproc/vp_debug.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- vp_debug.c	3 Feb 2009 06:18:13 -0000	1.14
+++ vp_debug.c	27 Oct 2009 03:18:30 -0000	1.15
@@ -168,7 +168,9 @@
 	printk("tgid=%d\n", p->tgid);
 	printk("cltnode=%d\n", p->cltnode);
 	printk("p_vproc=0x%p\n", p->p_vproc);
+#ifdef SSI_NOTUSED
 	printk("p_vfparent=0x%p\n", p->p_vfparent);
+#endif
 	printk("group_leader=0x%p\n", p->group_leader);
 	printk("&pids=0x%p\n", p->pids);
 	printk("set_child_tid 0x%p\n", p->set_child_tid);

Index: procfs_subr.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/vproc/procfs_subr.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- procfs_subr.c	24 Mar 2009 04:26:28 -0000	1.15
+++ procfs_subr.c	27 Oct 2009 03:18:30 -0000	1.16
@@ -202,7 +202,7 @@
 	 * in the kernel, or if loadleveling has been turned
 	 * off for a node
 	 */
-	if (!loadlevel_on)
+	if (!atomic_read(&loadlevel_on))
 		return;
 
 	for (i = 0; i < vprochsz; i++) {
@@ -244,10 +244,14 @@
 				/* skip processes that are currently loadleveled */
 				if (pvp->pvp_loadlevel)
 					continue;
+#ifdef LOADLEVEL_TABLE_LIST
+				set_mb(pvp->pvp_loadlevel, -1);
+#else
 				if (!TRY_VPROC_LOCK_EXCL(vp, "ssi_reset_loadlevel"))
 					continue;
 				pvp->pvp_loadlevel = -1;
 				VPROC_UNLOCK_EXCL(vp, "ssi_reset_loadlevel");
+#endif
 			}
 #ifdef VPROC_HASH_LIST
 		}
@@ -284,6 +288,8 @@
 	return 0;
 }
 
+/* Called/returns with read tasklist_lock */
+/* Might release/re-acquire tasklist_lock */
 int
 ssi_tty_get_pgrp(struct task_struct *p, int *pgrp)
 {

Index: dvp_pvpsops.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/vproc/dvp_pvpsops.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- dvp_pvpsops.c	24 Mar 2009 04:26:28 -0000	1.18
+++ dvp_pvpsops.c	27 Oct 2009 03:18:29 -0000	1.19
@@ -58,7 +58,7 @@
 
 static pid_t capability_lock_owner = -1; /* owner of capability lock */
 static DECLARE_WAIT_QUEUE_HEAD(capability_wqh);
-static DEFINE_SPINLOCK(capability_spin_lock);
+static __cacheline_aligned_in_smp DEFINE_SPINLOCK(capability_spin_lock);
 
 #define RPVPSOP_START(_node,_error,_id_string)				\
 	_error = 0
@@ -703,7 +703,6 @@
 #endif
 
 		pvp->pvp_flag &= (~flags | PV_SESS_ORIGIN);
-
 		if (flags & PV_SESS_ORIGIN) {
 			/*
 			 * If the session leader hasn't exited yet then
@@ -767,10 +766,16 @@
 
 	/* Down all ICS interfaces */
 	read_lock(&dev_base_lock);
+	/* SSI_XXX: might_sleep in following path:
+	 * dev_close, notifier_call_chain, rtnetlink_event, rtmsg_ifinfo,
+	 * alloc_skb, kmem_cache_alloc
+	 */
 	for (dev = dev_base; dev != NULL; dev = dev->next) {
 		if (dev->priv_flags & IFF_ICS) {
 			dev->priv_flags &= ~IFF_ICS;
+			//rtnl_lock(); /* for notifier_call_chain() */
 			dev_close(dev);
+			//rtnl_unlock();
 		}
 	}
 	read_unlock(&dev_base_lock);
@@ -1042,22 +1047,19 @@
 			spin_lock(&capability_spin_lock);
 		}
 		ssi_block_signals(current, &old_blocked);
+		add_wait_queue_exclusive(&capability_wqh, &wait);
 		while (capability_lock_owner != -1 &&
 		       capability_lock_owner != lock_pid) {
-			add_wait_queue_exclusive(&capability_wqh, &wait);
 			set_current_state(TASK_INTERRUPTIBLE);
 			spin_unlock(&capability_spin_lock);
 			schedule();
-			remove_wait_queue(&capability_wqh, &wait);
 			spin_lock(&capability_spin_lock);
 		}
+		remove_wait_queue(&capability_wqh, &wait);
 		capability_lock_owner = lock_pid;
-		spin_unlock(&capability_spin_lock);
 		ssi_unblock_signals(current, &old_blocked);
 	}
-	else
-		spin_unlock(&capability_spin_lock);
-
+	spin_unlock(&capability_spin_lock);
 
 	return 0;
 }
@@ -1662,14 +1664,13 @@
 	if (*pidlist == NULL)
 		*pidlist = kmalloc_nofail(pidlistsz);
 
-#ifdef VPROC_RCU_LIST
-	rcu_read_lock();
-#else
+#ifndef VPROC_RCU_LIST
 	VPROC_LIST_LOCK();
 #endif
 	for (index = 0, count = 0; index < vprochsz; index++) {
 #ifdef VPROC_HASH_LIST
 #ifdef VPROC_RCU_LIST
+		rcu_read_lock();
 		list_for_each_entry_rcu(vp, &vproc_hash[index], vp_list) {
 #else
 		list_for_each_entry(vp, &vproc_hash[index], vp_list) {
@@ -1688,10 +1689,11 @@
 				(*pidlist)[count] = vp->vp_pid;
 			count++;
 		}
-	}
 #ifdef VPROC_RCU_LIST
-	rcu_read_unlock();
-#else
+		rcu_read_unlock();
+#endif
+	}
+#ifndef VPROC_RCU_LIST
 	VPROC_LIST_UNLOCK();
 #endif
 
@@ -1763,17 +1765,20 @@
 	/* perform local operation */
 
 #ifdef LOADLEVEL_TABLE_LIST
-	LOADLIST_LOCK_SHARED();
-	if (action && list_empty(&loadlevel_table))
-		printk("Warning: /proc/cluster/loadlevellist is empty\n");
-	LOADLIST_UNLOCK_SHARED();
+	if (action) {
+		LOADLIST_LOCK_SHARED();
+		if (list_empty(&loadlevel_table))
+			printk("Warning: /proc/cluster/loadlevellist is empty\n");
+		LOADLIST_UNLOCK_SHARED();
+	}
 #else
 	if (action && !loadlevel_table)
 		printk("Warning: /proc/cluster/loadlevellist is empty\n");
 #endif
 
 	/* get some lock */
-	loadlevel_on = action;
+	/* loadlevel_on = action; */
+	atomic_set(&loadlevel_on, action);
 #endif
 	/* release some lock */
 	return 0;

Index: dvp_vpops.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/vproc/dvp_vpops.c,v
retrieving revision 1.40
retrieving revision 1.41
diff -u -d -r1.40 -r1.41
--- dvp_vpops.c	24 Mar 2009 04:26:28 -0000	1.40
+++ dvp_vpops.c	27 Oct 2009 03:18:29 -0000	1.41
@@ -43,6 +43,7 @@
 #endif
 
 #include <cluster/assert.h>
+#include <cluster/async.h>
 
 #include <cluster/gen/rproc.h>
 
@@ -98,7 +99,6 @@
 	int flags)		/* flag values */
 {
 	struct pvproc *pvp = PVP(vp);
-	int sig_received;
 
 	VPROC_LOCK_FLAG(vp, "vpop_fork startup");
 
@@ -107,11 +107,12 @@
 
 	VPROC_UNLOCK_FLAG(vp, "vpop_fork startup");
 
+#ifdef SSI_SKIP
 #ifdef VPROC_HOLD_ZERO_GET_TASK
 	WARN_ON(!PV_IS_ALIVE(pvp));
 #endif
-	sig_received = pproc_signal_received(pvp->pvp_pproc, flags);
-	if (sig_received)
+#endif
+	if (pproc_signal_received(pvp->pvp_pproc, flags))
 		return (-ERESTARTNOINTR);
 
         return(ESUCCESS);
@@ -388,6 +389,8 @@
 #endif
 	VPROC_LIST_UNLOCK();
 	VPROC_HOLD(vc, "vpop_fork(origin)");
+	VPROC_HOLD(vc, "vpop_fork(child)");
+	VPROC_HOLD(pp, "vpop_fork(parent)");
 
 #ifndef VPROC_LOCKING_CONTEXT_FIX
 	VPROC_LOCK_FLAG(vc, "vpop_fork");
@@ -399,7 +402,6 @@
 	PVP_ADD_PARENT(pvc, pvp);
 #else
 	pvc->pvp_childl = pvp->pvp_head_childl; /* put child on its parent's */
-	mb();
 	pvp->pvp_head_childl = vc;	/* child list */
 	pvc->pvp_head_childl = NULL;	/* child has no children */
 #endif /* !VPROC_PVP_CHILD_LL */
@@ -416,20 +418,22 @@
 	pvc->pvp_loadlevel = pvp->pvp_loadlevel; /* child inherits loadlevel */
 	pvc->pvp_localview = pvp->pvp_localview; /* child inherits view */
 
-#ifndef VPROC_LOCKING_CONTEXT_FIX
-	 if (!(local_flags & IS_KTHREAD)) {
-		 /* if not a kernel daemon(kernel daemons cant move) and parent
-		  * hasnt been set yet then set it now, so child
-		  * can set loadlevel properly as well.
-		  */
+	if (!(local_flags & IS_KTHREAD)) {
+		/* if not a kernel daemon(kernel daemons cant move) and parent
+		 * hasnt been set yet then set it now, so child
+		 * can set loadlevel properly as well.
+		 */
 #ifdef CONFIG_LDLVL
-		 if (pvc->pvp_loadlevel < 0) {
+		if (pvc->pvp_loadlevel < 0) {
+#ifdef TASK_HOLD_VPROC
+			(void) vproc_is_loadlevelable(pp, NULL);
+#else
 			(void)is_loadlevelable(pvp->pvp_pproc, NULL);
+#endif
 			pvc->pvp_loadlevel = pvp->pvp_loadlevel;
-		 }
+		}
 #endif
 	}
-#endif /* !VPROC_LOCKING_CONTEXT_FIX */
 	/*
 	 * These values are only guaranteed to be accurate at the origin
 	 * node of the process.
@@ -462,19 +466,24 @@
 
 	VPROC_UNLOCK_FLAG(vc, "vpop_fork");
 
-	VPROC_HOLD(vc, "vpop_fork(child)");
-	VPROC_HOLD(pp, "vpop_fork(parent)");
-
 	if (pvp->pvp_pgid != 0) {
-		/* the child joins its parent's group */
+		/*
+		 * Have the child join its parent's pgrp.
+		 * Normally we should now do a VPROC_HOLD(g) to keep a
+		 * reference to the pgrp leader.  Instead we just skip doing
+		 * a VPROC_RELE(g) for the LOCATE_VPROC_PID() below.
+		 */
+#ifdef VPROC_RELEASE__REFCNT_RACE_FIX
+		struct vproc *g = LOCATE_VPROC_PID_ORIGIN(pvp->pvp_pgid,
+					"vpop_fork(pgrp leader on member node");
+		SSI_ASSERT(g);
+#else
 		struct vproc *g = VPROCPTR(pvp->pvp_pgid);
 		VPROC_HOLD(g, "vpop_fork(pgrp leader on member node)");
+#endif
 		if (local_flags & IS_KTHREAD)
         		pvc->pvp_pgrp_mem_seqno = -1;
 		dvp_child_join_pgrp_end(pp, vc, g);
-#ifdef VPROC_RELEASE__REFCNT_RACE_FIX
-		VPROC_RELE(g, "temp vpop_fork(pgrp leader on member node)");
-#endif
 	}
 
 #ifdef CONFIG_VPROC_ND
@@ -666,14 +675,14 @@
 			*node = i;
 		}
 	}
-#else
+#else /* CONFIG_MOSIX_LL */
 	*node = CLUSTERNODE_INVAL;
 #ifdef CONFIG_SSI_RR_DEBUG
 	if (ssi_roundrobin)
 		goto rr;
 #endif
 	consider(BALANCE, NULL, node);
-#endif /* !CONFIG_MOSIX_LL */
+#endif /* CONFIG_MOSIX_LL */
 #ifdef CONFIG_SSI_RR_DEBUG
 rr:
 	if (ssi_roundrobin) {
@@ -694,9 +703,9 @@
 		return 0;
 	}
 #endif
-#else
+#else /* !CONFIG_LDLVL */
 	*node = CLUSTERNODE_INVAL;
-#endif
+#endif /* !CONFIG_LDLVL */
 	return 0;
 }
 
@@ -747,12 +756,13 @@
 #ifdef VPROC_PVP_CHILD_LL
 	struct pvproc *pc, *n;
 #endif
-	procinfo_t pinfo;
 	int error;
 
 	VPROC_HOLD(v, "vpop_exit(exit)");
 	VPROC_LOCK_EXCL(v, "vpop_exit");
 
+	SSI_ASSERT(tsk);
+
 	VPROC_LOCK_FLAG(v, "vpop_exit");
 	pv->pvp_flag |= PV_EXITING;
 	VPROC_UNLOCK_FLAG(v, "vpop_exit");
@@ -781,7 +791,6 @@
 		 */
 		VPROC_LOCK_ND_LIST_EXCL(v, "vpop_exit");
 		pv->pvp_head_childl = PVP(vc)->pvp_childl;
-		mb();
 		PVP(vc)->pvp_childl = NULL;
 		VPROC_UNLOCK_ND_LIST_EXCL(v, "vpop_exit");
 #endif /* !VPROC_PVP_CHILD_LL */
@@ -802,9 +811,6 @@
 							 vc,
 							 PVWS_SGHOST,
 							 0);
-#ifdef VPROC_RELEASE__REFCNT_RACE_FIX
-			VPROC_RELE(vi, "vpop_cleanup_vproc_relations(vprocptr vi)");
-#endif
 
 			/*
 			 * Change the parent cares about child care
@@ -847,30 +853,31 @@
 	 * This avoids process 0 performing a PV_NOCLDWAIT reap.
 	 */
 	if (v->vp_pid != 1) {
+		procinfo_t pinfo;
 #ifndef RELEASE_TASK_LEADER_GONE__VPROC_FIX
 		struct vproc *p = VPROCPTR(pv->pvp_ppid);
 #endif
 		int sig;
+
 		/*
 		 * Mark the vproc as a zombie and report the zombie
 		 * status to the parent.
 		 */
-
 		tsk->exit_state = EXIT_ZOMBIE;
-
 		pproc_pinfo(tsk, &pinfo);
+
 		/* System processes dont have exit signal set.  Since
 		 * system processes will now be reaped by pid 2, a
 		 * SIGCHLD will be sent to pid 2
 		 */
-		sig = (IS_SYSPROC(pv) && (pv->pvp_ppid == 2) ?
-			(vproc_child_reaper_ready ? SIGCHLD : 0) :
-			tsk->exit_signal);
-		if (tsk->ptrace)
+		if (!tsk->ptrace) {
+			sig = (IS_SYSPROC(pv) && (pv->pvp_ppid == 2) ?
+				(vproc_child_reaper_ready ? SIGCHLD : 0) :
+				tsk->exit_signal);
+		} else
 			sig = SIGCHLD;
 #ifdef RELEASE_TASK_LEADER_GONE__VPROC_FIX
-		(void) VPOP_REPORT_STATE(v, sig, &pinfo,
-						VPROC_ZOMBIE, 0);
+		(void) VPOP_REPORT_STATE(v, sig, &pinfo, VPROC_ZOMBIE, 0);
 #else
 		VPROC_LOCK_FLAG(v, "vpop_exit");
 		pv->pvp_wstate = PVWS_SZOMB;
@@ -888,20 +895,15 @@
 			ssi_clear_task_execnode(tsk);
 	}
 
-	/* Need to null out itimers */
+	/*
+	 * Clear these here so that update_process_times() won't try to deliver
+	 * itimer, profile or rlimit signals to this task while it is in late exit.
+	 */
 	tsk->it_virt_value = cputime_zero;
 	tsk->it_prof_value = cputime_zero;
 
 	VPROC_UNLOCK_EXCL(v, "vpop_exit");
-
 	VPROC_RELE(v, "vpop_exit(exit)");
-
-#ifdef SSI_SKIP
-	/* Need to set the tsk->flags to PF_DEAD so schedule() can
-	 * do put_task_struct()
-	 */
-	tsk->flags |= PF_DEAD;
-#endif
 }
 
 /*
@@ -922,13 +924,13 @@
 	struct pusage_dev *pu_loc,	/* pointer to child resource usage */
 	pid_t *ret_val)			/* awaited pid */
 {
-	register struct pvproc *pvp = PVP(vp);
-	register struct vproc *vc = NULL;
-	register struct pvproc *pvc;
+	struct pvproc *pvp = PVP(vp);
+	struct vproc *vc = NULL;
+	struct pvproc *pvc;
 #ifdef VPROC_PVP_CHILD_LL
 	struct pvproc *n;
 #else
-	register struct vproc *vo;
+	struct vproc *vo;
 #endif /* !VPROC_PVP_CHILD_LL */
 	int found;
 	int cur_options = 0;
@@ -943,22 +945,12 @@
 
 #ifdef VPROC_VPROC_WNOTHREAD
 #ifndef VPROC_WAIT_THREADS
-#define VPROC_WAIT_THREADS(_vp, _options) {			\
-		if (!(_options & VPROC_WNOTHREAD)) {		\
-			task_t *tsk = PVP(_vp)->pvp_pproc;	\
-			read_lock(&tasklist_lock);		\
-			tsk = next_thread(tsk);			\
-			if (tsk->signal != current->signal)	\
-				BUG();				\
-			read_unlock(&tasklist_lock);		\
-			if (tsk != current) {			\
-				/* next thread */		\
-				break;				\
-			}					\
-		}						\
-	}
-#endif
+#define VPROC_WAIT_THREADS do { \
+	*ret_val = ret; \
+	error = -EBUSY; \
+} while (0)
 #endif
+#endif /* VPROC_VPROC_WNOTHREAD */
 
 #ifdef VPROC_DEBUG
 	extern int vpoptrace;
@@ -977,6 +969,7 @@
 	 * a pid of 0 requests any child in the parent's process group
 	 * or a pid < 0 specifies another process group
 	 */
+#ifdef SSI_SKIP
 	if (pid == WAIT_ANY)
 		pgid = WAIT_ANY;
 	else if (pid > 0)
@@ -985,6 +978,13 @@
 		pgid = pvp->pvp_pgid;
 	else if (pid < 0)
 		pgid = -pid;
+#else
+	/* SSI_ASSERT(pgid == WAIT_ANY); */
+	if (pid == 0)
+		pgid = pvp->pvp_pgid;
+	else if (pid < WAIT_ANY)
+		pgid = -pid;
+#endif
 
 loop:
 	found = FALSE;
@@ -1024,9 +1024,19 @@
 #ifdef DE_THREAD__OOPS_FIX
 			if (vc->vp_pid != pid ) {
 				/* SSI_XXX: potentially remote */
+				/* Will not be remote since entire
+				 * thread group migrates.
+				 */
+#ifdef TASK_HOLD_VPROC
+				if ((PVP(vc)->pvp_flag & PV_IS_LOCAL) &&
+				    PVP(vc)->pvp_pproc && PVP(vc)->pvp_pproc->pid == pid)
+#else
 				if (PVP(vc)->pvp_pproc &&
 				    PVP(vc)->pvp_pproc->pid == pid)
-					/* de_thread() switched pproc pids */
+#endif
+					/* switch_exec_pids() switched pids
+					 * with previous thread group leader.
+					 */
 					switch_exec_pids = 1;
 				else
 					continue;
@@ -1040,6 +1050,7 @@
 		pvc = PVP(vc);
 #endif
 
+		VPROC_LOCK_FLAG(vc, "vpop_wait");
 #ifdef VPROC_DEBUG
 		if (vpoptrace)
 		if (pvc->pvp_flag & PV_ISWAITCLONE)
@@ -1053,8 +1064,10 @@
 		 * using a signal other than SIGCHLD.) */
 
 		if (((pvc->pvp_flag & PV_ISWAITCLONE) ^ (options & VPROC_WNCW))
-		    && !(options & VPROC_WALL))
+		    && !(options & VPROC_WALL)) {
+			VPROC_UNLOCK_FLAG(vc, "vpop_wait");
 			continue;
+		}
 #ifdef VPROC_DEBUG
 		if (vpoptrace)
 		printk("%d is waitable\n", (int) vc->vp_pid);
@@ -1082,6 +1095,9 @@
 			 */
 			if (pgid > 0 && !found) {
 				pid_t vc_pgid;
+
+				VPROC_UNLOCK_FLAG(vc, "vpop_wait");
+
 				ret = PVPOP_GETATTR(vc, 0, 0, &vc_pgid, 0, 0, 0, 0,
 						    TRUE);
 /* #ifdef DEBUG
@@ -1090,8 +1106,12 @@
 						(int) pgid, (int) vc->vp_pid,
 						(int) vc_pgid);
 #endif DEBUG */
-				if ((ret == 0) && (vc_pgid == pgid))
+				if ((ret == 0) && (vc_pgid == pgid)) {
+#ifdef VPROC_VPROC_WNOTHREAD
+					VPROC_WAIT_THREADS;
+#endif
 					found = TRUE;
+				}
 				continue;
 			}
 		}
@@ -1104,8 +1124,11 @@
 		switch (pvc->pvp_wstate) {
 
 		case PVWS_SZOMB:
-			if (pvp->pvp_flag & PV_NOCLDWAIT)
+			if (pvp->pvp_flag & PV_NOCLDWAIT) {
+				VPROC_UNLOCK_FLAG(vc, "vpop_wait");
 				break;
+			}
+			VPROC_UNLOCK_FLAG(vc, "vpop_wait");
 
 			/* (potentially) go remote to get status */
 			cur_options = (options & (VPROC_WZOMBIE|VPROC_WNOWAIT));
@@ -1128,10 +1151,8 @@
 				/* thread group leader of a non empty list */
 				if (ret == -EBUSY)
 					found = TRUE;
-				if (ret == -EDEADLK) {
-#else
-				if (ret == -EAGAIN || ret == -EDEADLK) {
 #endif
+				if (ret == -EDEADLK) {
 					VPROC_UNLOCK_EXCL(vp, "vpop_wait");
 #ifdef VPROC_RW_LOCK
 					idelay(HZ/10);
@@ -1139,12 +1160,12 @@
 					goto loop;
 				}
 #ifdef VPROC_VPROC_WNOTHREAD
-				else
-				/* thread group leader of a non empty list */
-				if (ret == -EBUSY) {
-					VPROC_WAIT_THREADS(vp, options);
+				else if (ret == -EBUSY) {
+					/* thread group leader of a non empty list */
+					VPROC_WAIT_THREADS;
 					found = TRUE;
 				}
+				/* Base: no repeat for -EAGAIN */
 #endif
 				break;
 			}
@@ -1186,12 +1207,11 @@
 #ifdef VPROC_PVP_CHILD_LL
 				PVP_REMOVE_PARENT(pvc);
 #else
-				if (vo == NULL) {
+				if (vo == NULL)
 					pvp->pvp_head_childl = pvc->pvp_childl;
-				} else {
+				else
 					PVP(vo)->pvp_childl = pvc->pvp_childl;
-				}
-				mb();
+				rmb();
 				pvc->pvp_childl = NULL;
 #endif /* !VPROC_PVP_CHILD_LL */
 				VPROC_UNLOCK_ND_LIST_EXCL(vp, "vpop_wait");
@@ -1216,10 +1236,13 @@
 
 #ifdef CONFIG_VPROC_ND
 		case PVWS_SGHOST:
-			if (!(options & VPROC_WZOMBIE))
+			if (pvp->pvp_flag & PV_NOCLDWAIT) {
+				VPROC_UNLOCK_FLAG(vc, "vpop_wait");
 				break;
+			}
+			VPROC_UNLOCK_FLAG(vc, "vpop_wait");
 
-			if (pvp->pvp_flag & PV_NOCLDWAIT)
+			if (!(options & VPROC_WZOMBIE))
 				break;
 
 			bzero(pu_loc, sizeof(struct pusage_dev));
@@ -1251,7 +1274,7 @@
 				pvp->pvp_head_childl = pvc->pvp_childl;
 			else
 				PVP(vo)->pvp_childl = pvc->pvp_childl;
-			mb();
+			rmb();
 			pvc->pvp_childl = NULL;
 #endif /* !VPROC_PVP_CHILD_LL */
 			VPROC_UNLOCK_ND_LIST_EXCL(vp, "vpop_wait");
@@ -1301,6 +1324,8 @@
 				cur_options = (options &
 					(VPROC_WTRAPPED|VPROC_WNOWAIT));
 
+			VPROC_UNLOCK_FLAG(vc, "vpop_wait");
+
 			*ret_val = vc->vp_pid;
 			/* (potentially) go remote to get status */
 #ifdef VPROC_RW_LOCK
@@ -1312,11 +1337,7 @@
 				/* Didnt find a matching child */
 				if (ret == -ESRCH)
 					break;
-#ifndef VPROC_VPROC_WNOTHREAD
 				if (ret == -EDEADLK) {
-#else
-				if (ret == -EAGAIN || ret == -EDEADLK) {
-#endif
 					VPROC_UNLOCK_EXCL(vp, "vpop_wait");
 #ifdef VPROC_RW_LOCK
 					idelay(HZ/10);
@@ -1324,7 +1345,7 @@
 					goto loop;
 				}
 #ifdef VPROC_VPROC_WNOTHREAD
-				VPROC_WAIT_THREADS(vp, options);
+				VPROC_WAIT_THREADS;
 #endif
 				/*
 				 * It's stopped now, so it might later
@@ -1362,6 +1383,7 @@
 			return(ESUCCESS);
 
 		default:
+			VPROC_UNLOCK_FLAG(vc, "vpop_wait");
 			/*
 			 * If the wait is on a particular pgid, then we should
 			 * check the child's pgid to see if it matches. Since
@@ -1380,7 +1402,9 @@
 				if ((ret != 0) || (vc_pgid != pgid))
 					break;
 			}
-
+#ifdef VPROC_VPROC_WNOTHREAD
+			VPROC_WAIT_THREADS;
+#endif
 			found = TRUE;
 			break;
 		}
@@ -1397,6 +1421,7 @@
 		printk("vpop_wait: no child found\n");
 #endif /* VPROC_DEBUG */
 		error = -ECHILD;
+#ifndef VPROC_VPROC_WNOTHREAD
 	} else if (options & VPROC_WNOHANG) {
 #ifdef VPROC_DEBUG
 		if (vpoptrace)
@@ -1423,6 +1448,7 @@
 		} else {
 			goto loop;
 		}
+#endif /* !VPROC_VPROC_WNOTHREAD */
 	}
 
 /* #ifdef DEBUG
@@ -1487,6 +1513,80 @@
 }
 
 
+struct report_state_async {
+	struct vproc *vp;
+	int sig;
+	int have_pinfo;
+	procinfo_t pinfo;
+	int state;
+};
+
+void
+vpop_report_state_async_handler(
+	void *args)
+{
+	struct report_state_async *data = (struct report_state_async *) args;
+	struct vproc *v = data->vp;
+
+	/* Grab VPROC LOCK here to prevent async_queue again. */
+	VPROC_LOCK_EXCL(v, "vpop_report_state_async_handler");
+
+	(void)vpop_report_state(v,
+				data->sig,
+				data->have_pinfo ? &data->pinfo : NULL,
+				data->state,
+				0);
+	VPROC_UNLOCK_EXCL(v, "vpop_report_state_async_handler");
+	/* Release the hold in __vpop_report_state() */
+	VPROC_RELE(v, "vpop_report_state_async_handler");
+}
+
+static inline int
+__vpop_report_state(
+	struct vproc *v,	/* vproc of process changing state */
+	int sig,		/* signal to send */
+	procinfo_t *pinfo,	/* calling process information */
+	int state)		/* zombie or stop or unstop */
+{
+	struct report_state_async *data;
+	int error;
+
+	if (TRY_VPROC_LOCK_EXCL(v, "vpop_report_state"))
+		return 0;
+
+	/* Check whether we could deadlock with pvpop_add_pgrp_list()
+	 * in do_fork() path.
+	 */
+	if (!VPROC_LOCK_PGRP_LIST_EXCL_HELD(v)) {
+		VPROC_LOCK_EXCL(v, "vpop_report_state");
+		return 0;
+	}
+
+	data = kmalloc(sizeof(*data), GFP_KERNEL);
+	if (data) {
+		VPROC_HOLD(v, "vpop_report_state_async_handler");
+		data->vp = v;
+		data->sig = sig;
+		data->have_pinfo = (pinfo != NULL);
+		if (data->have_pinfo)
+			data->pinfo = *pinfo;
+		data->state = state;
+		error = nsc_async_queue(nsc_generic_async_queue,
+				vpop_report_state_async_handler,
+				data,
+				sizeof(*data),
+				NSC_ASYNC_DUPCHECK | NSC_ASYNC_ARGS_FREE);
+		if (!error)
+			return -EDEADLK; /* Successfully queued */
+
+		printk(KERN_WARNING "%s: unable to allocate async event; error=%d\n",
+				__FUNCTION__, error);
+	}
+	/* SSI_XXX: Do we want to retry? */
+	VPROC_LOCK_EXCL(v, "vpop_report_state");
+	return 0;
+}
+
 /*
  * NAME:	vpop_report_state
  *
@@ -1510,8 +1610,17 @@
 #endif
 
 	if (!local_only) {
-		if (!held)
-			VPROC_LOCK_EXCL(v, "temp report_state");
+		if (!held) {
+			error = __vpop_report_state(v, sig, pinfo, state);
+			if (error == -EDEADLK) {
+				/* Return value is not pvpop_report_state()
+				 * but is okay for now, caller doesn't care.
+				 */
+				return 0;
+			}
+			/* Got VPROC LOCK */
+			/* VPROC_LOCK_EXCL(v, "vpop_report_state"); */
+		}
 		if ((PVP(v)->pvp_wstate == PVWS_SZOMB) && 
 						(state != VPROC_ZOMBIE)) {
 #ifndef VPROC_CONTINUE
@@ -1519,7 +1628,7 @@
 			set_current_state(current_state);
 #endif
 			if (!held)
-				VPROC_UNLOCK_EXCL(v, "temp report_state");
+				VPROC_UNLOCK_EXCL(v, "vpop_report_state");
 			return 0;
 		}
 	}
@@ -1581,7 +1690,7 @@
 	/* SSI_XXX: still have to wake parent on wait4 */
 	else if (old_state == new_state) {
 		if (!held)
-			VPROC_UNLOCK_EXCL(v, "temp report_state");
+			VPROC_UNLOCK_EXCL(v, "vpop_report_state");
 		return 0;
 	}
 #endif
@@ -1630,8 +1739,14 @@
 		struct vproc *vp = LOCATE_VPROC_PID(PVP(v)->pvp_ppid,
 							"vpop_report_state");
 		if (vp) {
+#ifdef VPROC_HOLD_ZERO_GET_TASK
+			/* Prevent bogus parent pvp_pproc */
+			VPROC_HOLD_MOVEMENT(vp, "vpop_report_state");
+#endif
 			parent = PVP(vp)->pvp_pproc;
+#ifdef SSI_SKIP
 #ifdef VPROC_VPROC_WNOTHREAD
+			/* SSI_XXX: Processes do not reap themselves */
 			if (state == VPROC_ZOMBIE &&
 			    PVP(vp)->pvp_flag & PV_IS_LOCAL) {
 				read_lock(&tasklist_lock);
@@ -1644,6 +1759,7 @@
 					read_unlock(&tasklist_lock);
 			} else
 #endif
+#endif /* SSI_SKIP */
 #ifdef VPROC_CONTINUE_SIGCHLD
 			/* Create pinfo for (remote) parent
 			 * required for glibc waitid test
@@ -1661,15 +1777,19 @@
 		if (state == VPROC_ZOMBIE) {
 			if (unlikely(!vp || error)) {
 				dpvproc_nocldwait_async_queue(vp, v);
-				sig = -1;
+				sig = -2;
 			}
-			if (sig == -1) {
-#ifdef VPROC_VPROC_WNOTHREAD
+			//if (sig == -1) {
+			if (sig < 0) {
+#if defined(VPROC_VPROC_WNOTHREAD) && defined(SSI_SKIP)
+				/* SSI_XXX: Processes do not reap themselves */
 				read_lock(&tasklist_lock);
 				if (thread_group_empty(tsk))
 					tsk->exit_signal = -1;
-				if (likely(tsk->ptrace == 0) ||
-				    unlikely(parent && (parent->signal->flags & SIGNAL_GROUP_EXIT))) {
+				if (sig != -2 &&
+				    (likely(tsk->ptrace == 0) ||
+				     unlikely(parent && (parent->signal->flags &
+								SIGNAL_GROUP_EXIT)))) {
 					read_unlock(&tasklist_lock);
 					dpvproc_nocldwait_async_queue(vp, v);
 				} else
@@ -1682,25 +1802,37 @@
 		/*
 		 * Even if SIGCHLD is not generated, we must wake up wait4 calls.
 		 */
-		if (parent && v->vp_pid != tsk->tgid) {
+		if (parent && v->vp_pid != tsk->tgid && !thread_group_empty(parent)) {
 			tsk = parent;
 			/* Need to wake up every thread in parent group */
 			read_lock(&tasklist_lock);
+			if (!pid_alive(parent))
+				goto skip_threads;
 			while_each_thread(parent, tsk) {
 #ifdef LINUX_SSI_EVENT
-				VPROC_WAIT_EVENT_SIGNAL(tsk->p_vproc);
+#ifdef TASK_HOLD_VPROC
+				if (!tsk->p_vproc) /* Raced with process creation */
+					continue;
+#endif
+				if (!(tsk->flags & PF_EXITING))
+					VPROC_WAIT_EVENT_SIGNAL(tsk->p_vproc);
 #else
 				VPROC_WAIT_EVENT_BROADCAST(tsk->p_vproc);
 #endif
 			}
+skip_threads:
 			read_unlock(&tasklist_lock);
 		}
-		if (vp)
+		if (vp) {
+#ifdef VPROC_HOLD_ZERO_GET_TASK
+			VPROC_RELEASE_MOVEMENT(vp, "vpop_report_state");
+#endif
 			VPROC_RELE(vp, "vpop_report_state");
+		}
 #endif /* RELEASE_TASK_LEADER_GONE__VPROC_FIX */
 
 		if (!held)
-			VPROC_UNLOCK_EXCL(v, "temp report_state");
+			VPROC_UNLOCK_EXCL(v, "vpop_report_state");
 	}
 
 	return error;
@@ -1904,6 +2036,7 @@
  *		if the process is a pgrp ldr, pass it on to the members.
  *
  */
+/* Might be called with tty_sem held */
 int
 vpop_setctty(
 	struct vproc *v,	/* vproc of process getting the ctty  */
@@ -2092,15 +2225,12 @@
 			pvc = PVP(vc);
 #endif /* !VPROC_PVP_CHILD_LL */
 
-			VPROC_LOCK_FLAG(v, __FUNCTION__);
 			if (pvc->pvp_flag & PV_WAITED) {
-				VPROC_UNLOCK_FLAG(v, __FUNCTION__);
 #ifndef VPROC_PVP_CHILD_LL
 				vc = PVP(vc)->pvp_childl;
 #endif
 				continue;
 			}
-			VPROC_UNLOCK_FLAG(v, __FUNCTION__);
 
 			if (pvc->pvp_wstate == PVWS_SZOMB) {
 #ifdef VPROC_PVP_CHILD_LL
@@ -2197,7 +2327,11 @@
 		 * add SIGCHLD to parent's signal set.
 		 */
 		if (is_ssig && func != (void *) SIG_DFL && func != (void *) SIG_IGN) {
-			VPROC_LOCK_EXCL(v, "dpvpop_sigaction(SIGCHLD)");
+#ifdef VPROC_RW_LOCK
+			VPROC_LOCK_SHARED(v, "vpop_sigaction(SIGCHLD)");
+#else
+			VPROC_LOCK_EXCL(v, "vpop_sigaction(SIGCHLD)");
+#endif
 #ifdef VPROC_PVP_CHILD_LL
 			PVP_CHILD_FOR_EACH(pvc, pvp) {
 #else
@@ -2212,7 +2346,11 @@
 					break;
 				}
 			}
+#ifdef VPROC_RW_LOCK
+			VPROC_UNLOCK_SHARED(v, "vpop_sigaction(SIGCHLD)");
+#else
 			VPROC_UNLOCK_EXCL(v, "vpop_sigaction(SIGCHLD)");
+#endif
 		}
 	}
 
@@ -2469,6 +2607,7 @@
 	return error;
 }
 
+/* Called with tty_sem held */
 struct tty_struct *
 ssi_release_tty(dev_t cttydev, clusternode_t cttynode, int exit)
 {
@@ -2507,6 +2646,9 @@
 #else
 	VPROC_LOCK_EXCL(v, "vpop_notify_parent");
 #endif
+#ifdef TASK_HOLD_VPROC
+	SSI_ASSERT(PVP(v)->pvp_flag & PV_IS_LOCAL);
+#endif
 	ret = do_notify_parent(PVP(v)->pvp_pproc, sig, 0, state);
 #ifndef VPROC_CONTINUE
 	/* SSI_XXX: wtf? */

Index: rproc_svr_pproc.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/vproc/rproc_svr_pproc.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -d -r1.25 -r1.26
--- rproc_svr_pproc.c	24 Mar 2009 04:26:28 -0000	1.25
+++ rproc_svr_pproc.c	27 Oct 2009 03:18:30 -0000	1.26
@@ -260,35 +260,41 @@
 	return error;
 }
 
-static inline void
+static void
 set_global_root(void)
 {
 	struct dentry *root, *old;
 	struct vfsmount *rootmnt, *oldmnt, *lastrootmnt;
 
-	write_lock(&current->fs->lock);
-	oldmnt = rootmnt = mntget(current->fs->rootmnt);
+	read_lock(&current->fs->lock);
+	oldmnt = mntget(current->fs->rootmnt);
 	old = dget(current->fs->root);
+	read_unlock(&current->fs->lock);
 
 	/* Find top-of-tree; don't use "rootfs" filesystem. */
-	spin_lock(&dcache_lock);
+	/* spin_lock(&dcache_lock); */
+	rootmnt = oldmnt;
+	spin_lock(&vfsmount_lock);
 	for (lastrootmnt = rootmnt;
 	     rootmnt != rootmnt->mnt_parent;
 	     lastrootmnt = rootmnt, rootmnt = rootmnt->mnt_parent)
 		;
-	rootmnt = lastrootmnt;
-	root = lastrootmnt->mnt_root;
-	spin_unlock(&dcache_lock);
+	if (lastrootmnt != oldmnt) {
+		mntget(rootmnt);
+		root = dget(rootmnt->mnt_root);
+	} else
+		root = NULL;
+	spin_unlock(&vfsmount_lock);
+	/* spin_unlock(&dcache_lock); */
 
-	if (root != old || rootmnt != oldmnt) {
-		mntput(current->fs->rootmnt);
-		dput(current->fs->root);
-		current->fs->rootmnt = mntget(rootmnt);
-		current->fs->root = dget(root);
+	if (lastrootmnt != oldmnt) {
+		set_fs_root(current->fs, rootmnt, root);
+		dput(root);
+		mntput(rootmnt);
 	}
-	mntput(oldmnt);
+
 	dput(old);
-	write_unlock(&current->fs->lock);
+	mntput(oldmnt);
 }
 
 /*
@@ -362,11 +368,12 @@
 	int		optype)
 {
 	struct task_struct *t = current;
-	int error;
-	unsigned long flags;
 	runqueue_t *rq;
-	int oldprio = 0;
+	unsigned long flags;
+	int error, oldprio = 0;
+
 #ifdef VPROC_UNLOAD_SETSCHED_SMP
+	/* set_daemon_prio(0, SCHED_NORMAL); */
 	write_lock_irq(&tasklist_lock);
 #endif
 	error = thread_info_unload_msg(&comm_datap->comm_thread_info, optype);
@@ -393,7 +400,7 @@
 	t->rt_priority = comm_datap->comm_rt_priority;
 	t->policy = comm_datap->comm_policy;
 	__activate_task(t, rq);
-	if (t->prio > oldprio)
+	if (t->prio != oldprio)
 		resched_task(t);
 	task_rq_unlock(rq, &flags);
 #ifndef VPROC_UNLOAD_SETSCHED_SMP
@@ -405,7 +412,6 @@
 	t->exit_signal = comm_datap->comm_exit_signal;
 #ifdef VPROC_UNLOAD_SETSCHED_SMP
 	write_unlock_irq(&tasklist_lock);
-	set_daemon_prio(0, SCHED_NORMAL);
 	set_binfmt(NULL); 	/* See as_unxscribe(). */
 #endif
 	set_personality(comm_datap->comm_personality);
@@ -466,8 +472,20 @@
 
 	array_cpy(t->comm, comm_datap->comm_comm);
 
-	if (!RVP_ISRFORK(optype))
-		semundo_unload_msg(&comm_datap->comm_sysvsem);
+	if (!RVP_ISRFORK(optype)) {
+#ifdef VPROC_MIGRATE_THREAD_GROUP_FIX
+		if (optype != RVP_MIGRATE_THREAD &&
+		    comm_datap->comm_sysvsem.semundolist_len == 0) {
+			/* Undo CLONE_SYSVSEM */
+			exit_sem(t);
+			t->sysvsem.undo_list = NULL;
+		} else
+#endif
+		/* SSI_XXX: no error handling in original */
+		error = semundo_unload_msg(&comm_datap->comm_sysvsem);
+		if (error)
+			goto out;
+	}
 
 	error = signal_unload_msg(comm_datap, optype);
 	if (error)

Index: as_xscribe.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/vproc/as_xscribe.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- as_xscribe.c	19 Feb 2009 08:01:02 -0000	1.17
+++ as_xscribe.c	27 Oct 2009 03:18:29 -0000	1.18
@@ -121,7 +121,7 @@
 int asx_hist_recs = (256 * 1024);
 int asx_hist_index;
 struct asx_hist_rec **asx_hist_top;
-DEFINE_SPINLOCK(asx_hist_lock);
+__cacheline_aligned_in_smp DEFINE_SPINLOCK(asx_hist_lock);
 DECLARE_MUTEX(asx_hist_init_sem);
 
 void
@@ -564,7 +564,7 @@
 			if (!let_go--) {
 				spin_unlock(&mm->page_table_lock);
 				up_read(&mm->mmap_sem);
-				yield();
+				/* yield(); */
 				goto loop;
 			}
 			asx_hist(2, asip->as_pid, addr, vma, pgdir);
@@ -597,7 +597,6 @@
 	struct vm_area_struct *vma;
 	struct task_struct *p;
 	struct vproc *v = NULL;
-	struct pvproc *pvp;
 	as_vma_info *avip;
 	int reopen_op;
 	int i;
@@ -613,10 +612,13 @@
 	}
 	v = VPROCPTR(pid);
 	SSI_ASSERT(v);
-	pvp = PVP(v);
 	if (v) {
-		p = pvp->pvp_pproc;
+		p = PVP(v)->pvp_pproc;
+#ifdef TASK_HOLD_VPROC
+		SSI_ASSERT(PVP(v)->pvp_flag & PV_IS_LOCAL);
+#else
 		SSI_ASSERT(p);
+#endif
 	} else
 		p = NULL;
 	if (!p) {
@@ -776,7 +778,6 @@
 	struct vm_area_struct *vma;
 	struct task_struct *p;
 	struct vproc *v = NULL;
-	struct pvproc *pvp;
 	as_pg_info *apip;
 	int isfile;
 	int isclustermap;
@@ -798,10 +799,13 @@
 	apip->api_deactivate = (op == ASX_MIGRATE);
 	v = VPROCPTR(pid);
 	SSI_ASSERT(v);
-	pvp = PVP(v);
 	if (v) {
-		p = pvp->pvp_pproc;
+		p = PVP(v)->pvp_pproc;
+#ifdef TASK_HOLD_VPROC
+		SSI_ASSERT(PVP(v)->pvp_flag & PV_IS_LOCAL);
+#else
 		SSI_ASSERT(p);
+#endif
 	} else
 		p = NULL;
 	if (!p) {
@@ -834,7 +838,7 @@
 			if (!let_go--) {
 				spin_unlock(&mm->page_table_lock);
 				up_read(&mm->mmap_sem);
-				yield();
+				/* yield(); */
 				goto loop;
 			}
 			asx_hist(5, pid, *addr, vma, pgdir);


------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay 
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.