[SSI] openssi/kernel/cluster/ssi/ipc ipcshm_svr.c,1.22,1.23

Roger Tsang <[email protected]> Sun, 21 Mar 2010 05:33:52 +0000
Newsgroups gmane.linux.cluster.ssic.cvs
Message-ID <[email protected]>
Update of /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/ipc
In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv21204/kernel/cluster/ssi/ipc

Modified Files:
      Tag: OPENSSI-FC
	ipcshm_svr.c 
Log Message:
IPC (#ifdef IPC_SHM_RACE_FIX):
- Fix livelock in do_ssi_shm_noclients() in svr_ripc_shm_cleanup() path due to deadlock with icssvr_nodedown_svc_wait() in ipc_shm_nodedown(). In do_ssi_shm_noclients() when RIPC_SHM_GET_NATTCHS() fails shm_nodelist in shmid_kernel_svr structure is re-read before retrying. It retries indefinitely. There is no livelock as long as down nodes are promptly removed from shm_nodelist, but the down node is not removed from shm_nodelist until after icssvr_nodedown_svc_wait() completes in ipc_shm_nodedown(). A deadlock occurs because icssvr_nodedown_svr_wait() waits for svr_ripc_shm_cleanup() to complete.
- Remove shm_sem_owned(). No longer used.
- Fix bug introduced in CVS tag OPENSSI-FC-1-9-6-PRE20. Remote SHM client stuck in shm_destroy(). cli_ripc_shm_cleanup() deadlock with ripc_shm_get_nattchs(). shm_ids.sem mutex is held during cli_ripc_shm_cleanup() which is a blocking RPC and triggers ripc_shm_get_nattchs() callback. A deadlock occurs when the callback waits for shm_ids.sem already held prior the RPC.
- ssi_shm_cleanup() at remote client no longer handles -EREMOTE (aka. node down); SHM segment is cleaned up during nodedown. Now ripc_shm_rmid() drops shm_ids.sem for caller since there is no longer need to return with shm_ids.sem held.
- Make abort_rmid() more robust during low memory.
- Fix RIPC_SHMCTL() in sys_shmctl(SHM_INFO) path deadlock with remote RIPC_SHM_GET_NATTCHS() in ssi_shm_cleanup() path.  Both callers hold shm_ids.sem at their node during RPC.

 cluster/ssi/ipc/ipcshm_svr.c  |   88 ++++++++++++++++++++--------------
 include/cluster/ssi/ipc/shm.h |    1 
 ipc/shm.c                     |   22 +++++---
 3 files changed, 67 insertions(+), 44 deletions(-)


Index: ipcshm_svr.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/ipc/ipcshm_svr.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- ipcshm_svr.c	7 Mar 2010 05:40:14 -0000	1.22
+++ ipcshm_svr.c	21 Mar 2010 05:33:50 -0000	1.23
@@ -251,9 +251,6 @@
 			ipc_get_locks(0, &shm_ids, 1);
 			cli_ipcname_rmid(NAME_SERVICE_SHM, id);
 			rval = ripc_shm_rmid(this_node, &rval, id, 1);
-#ifdef IPC_SHM_RACE_FIX
-			ipc_drop_locks(0, NULL, &shm_ids, 1);
-#endif
 		}
 
 		return rval;
@@ -266,14 +263,7 @@
 #ifdef IPC_SHM_RACE_FIX
 	nl = NSC_NODELIST_ALLOC();
 try_again:
-	if (dest == 2) {
-		WARN_ON(!shm_sem_owned());
-		svp = shm_svr_get(id);
-		if (svp)
-			ipc_lock_by_ptr(&svp->shm_perm);
-	} else
-		svp = shm_svr_lock(id);
-
+	svp = shm_svr_lock(id);
 	if (!svp) {
 		NSC_NODELIST_FREE(nl);
 		return -EIDRM;
@@ -285,6 +275,18 @@
 	cookie = CLUSTERNODE_INVAL;
 	while ((node = NSC_NODELIST_GET_NEXT(&cookie, nl))
 							!= CLUSTERNODE_INVAL) {
+		if (node == this_node)
+			continue;
+
+		ret = RIPC_SHM_GET_NATTCHS(node, &rval, id, &nattch, dest);
+		if (ret && ret != -EREMOTE) {
+			idelay(HZ);
+			goto try_again;
+		}
+		if (!rval && nattch)
+			cnt += nattch;
+	}
+	NSC_NODELIST_FREE(nl);
 #else /* IPC_SHM_RACE_FIX */
 try_again:
 	cnt = nm_svr_num;
@@ -294,13 +296,17 @@
 	cookie = CLUSTERNODE_INVAL;
 	while ((node = NSC_NODELIST_GET_NEXT(&cookie, svp->shm_nodelist))
 							!= CLUSTERNODE_INVAL) {
-#endif /* !IPC_SHM_RACE_FIX */
 		if (node == this_node)
 			continue;
 
 		ret = RIPC_SHM_GET_NATTCHS(node, &rval, id, &nattch, dest);
 
 		/* if error should get cleaned up by nodedown */
+		/* SSI_XXX: does not get cleaned up if we are
+		 * in svr_ripc_shm_cleanup() code path because nodedown
+		 * waits for us before removing node from shm_nodelist.
+		 *	-Roger
+		 */
 		if (ret) {
 			idelay(HZ);
 			goto try_again;
@@ -309,9 +315,7 @@
 		if (!rval && nattch)
 			cnt = cnt + nattch;
 	}
-#ifdef IPC_SHM_RACE_FIX
-	NSC_NODELIST_FREE(nl);
-#endif
+#endif /* !IPC_SHM_RACE_FIX */
 
 	return cnt;
 }
@@ -434,6 +438,7 @@
 /* Caller must assure shm_ids.sem is held.
  * Returns with shm_ids.sem released.
  */
+/* NB: shm_ids.sem held by ripc_shm_get_nattchs() during ssi_shm_cleanup() */
 int
 ripc_shm_rmid(
 	clusternode_t node,
@@ -445,14 +450,8 @@
 
 	shp = (struct shmid_kernel *)ipc_get_locks(id, &shm_ids, 0);
 	if (!shp) {
-#ifdef IPC_SHM_RACE_FIX
-		/* Drop the lock acquired during ripc_shm_get_nattchs() */
-		if (ssi_isremote())
-			ipc_drop_locks(0, NULL, &shm_ids, 1);
-#else
 		/* Drop the locks acquired by caller */
 		ipc_drop_locks(0, NULL, &shm_ids, 1);
-#endif
 		*rval = -EIDRM;
 		return 0;
 	}
@@ -461,10 +460,9 @@
 	BUG_ON(!size);
 	ssi_local_destroy(shp);
 #ifdef IPC_SHM_RACE_FIX
+	/* ssi_local_destroy() returns with shp unlocked */
 	ipc_set_lock_dest(&shm_ids, -1);
-	/* Drop the lock acquired during ripc_shm_get_nattchs() */
-	if (ssi_isremote())
-		ipc_drop_locks(0, NULL, &shm_ids, 1);
+	ipc_drop_locks(0, NULL, &shm_ids, 1);
 #else
 	ipc_drop_locks(id, (struct kern_ipc_perm *)shp, &shm_ids, 1);
 #endif
@@ -531,7 +529,7 @@
 
 #ifdef IPC_SHM_RACE_FIX
 	nl = NSC_NODELIST_ALLOC();
-
+retry:
 	svp = shm_svr_lock(id);
 	if (!svp) {
 		NSC_NODELIST_FREE(nl);
@@ -559,9 +557,14 @@
 
 		ret = RIPC_DROP_LOCKS(node, &rval, id);
 		(void) rval;
+#ifdef IPC_SHM_RACE_FIX
+		if (ret && ret != -EREMOTE) {
+			idelay(HZ);
+			goto retry;
+		}
+#endif
 	}
 	NSC_NODELIST_FREE(nl);
-	return;
 }
 
 int
@@ -610,7 +613,8 @@
 			 * unlocking unlocked lock in ripc_drop_locks.
 			 */
 			/* -EIDRM ? No. */
-			if (ret > 0)
+			//if (ret > 0)
+			if (ret != -EIDRM)
 #endif
 			/* drop remote locks because has attachs */
 			abort_rmid(id);
@@ -679,22 +683,19 @@
 			ipc_drop_locks(0, NULL, &shm_ids, 1);
 	}
 	else {
-		/* Drop the locks since will be going remote */
 		shp = shm_cli_get(id);
-#ifdef IPC_SHM_RACE_FIX
-		shm_cli_unlock(shp);
-		/* shm_ids.sem held */
-#else
+
+		/* Must drop locks since RIPC_SHM_CLEANUP() does
+		 * RIPC_SHM_GET_NATTCHS() callback which acquires shm_ids.sem
+		 */
 		ipc_drop_locks(id, (struct kern_ipc_perm *)shp, &shm_ids, 1);
-#endif
 
 		ret = RIPC_SHM_CLEANUP(svrnode, &rval, id, clinode);
 
-#ifndef IPC_SHM_RACE_FIX
 		/* Reacquire the locks */
 		ipc_get_locks(0, &shm_ids, 1);
-#endif
 
+#ifndef IPC_SHM_RACE_FIX
 #ifdef IPC_SHM_DESTROY_FIX
 		/* Ignore -EIDRM already removed at server */
 		if (ret == -EREMOTE) {
@@ -713,6 +714,23 @@
 		if (rval && rval != -EBUSY && rval != -ESRCH)
 			printk(KERN_WARNING "%s: Failed to cleanup IPC shm "
 				"structures %d\n", __FUNCTION__, rval);
+#else /* !IPC_SHM_RACE_FIX */
+		/* Ignore -EIDRM already removed at server */
+		/* Ignore -EREMOTE cleaned up by ipc_shm_nodedown() */
+		if (ret)
+			rval = ret;
+		switch (rval) {
+		case 0:
+		case -EBUSY:
+		case -ESRCH:
+			break;
+		default:
+			printk(KERN_WARNING "%s: Failed to cleanup IPC shm "
+				"structures %d\n", __FUNCTION__, rval);
+			break;
+		}
+		/* Return with shp unlocked */
+#endif /* IPC_SHM_RACE_FIX */
 	}
 	return 0;
 }


------------------------------------------------------------------------------
Download Intel&#174; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev