[SSI] openssi/kernel/ipc shm.c, 1.28, 1.29 util.c, 1.11, 1.12 util.h, 1.13, 1.14

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

Modified Files:
      Tag: OPENSSI-FC
	shm.c util.c util.h 
Log Message:
IPC (#ifdef IPC_SHM_RACE_FIX):
- ipc_shm_nodedown() optimize away ipc_ids->sem lock; acquire lock only if we encounter unattached segments. Restore code to track ID of SHM segment with SHM_DEST_LOCK flag.
- Regression:
  - vfsmount struct leak in ipc_shm_nodedown().

 cluster/ssi/ipc/ipcshm_svr.c |    8 ++-
 ipc/shm.c                    |   86 ++++++++++-------------------------
 ipc/util.c                   |   14 +++++
 ipc/util.h                   |    5 ++
 4 files changed, 53 insertions(+), 60 deletions(-)


Index: util.h
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/ipc/util.h,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- util.h	5 Mar 2010 06:30:21 -0000	1.13
+++ util.h	7 Mar 2010 05:40:14 -0000	1.14
@@ -34,6 +34,11 @@
 	int max_id;
 	unsigned short seq;
 	unsigned short seq_max;
+#ifdef CONFIG_SSI
+#ifdef IPC_SHM_RACE_FIX
+	int lock_dest_id; /* id of entry holding sem for SHM_LOCK_DEST */
+#endif
+#endif
 	struct semaphore sem;	
 	struct ipc_id_ary nullentry;
 	struct ipc_id_ary* entries;

Index: shm.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/ipc/shm.c,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -d -r1.28 -r1.29
--- shm.c	5 Mar 2010 06:30:21 -0000	1.28
+++ shm.c	7 Mar 2010 05:40:14 -0000	1.29
@@ -1514,41 +1514,37 @@
 void
 ipc_shm_nodedown(clusternode_t node)
 {
+#ifdef IPC_SHM_RACE_FIX
 	struct ipc_ids *ids = &shm_ids;
 	struct shmid_kernel *shp;
-	int id;
-#ifdef IPC_SHM_RACE_FIX
 	struct vfsmount *mnt;
-	int sem_held;
-	int last_id, max_id;
-	char retry, use_bitmap, shm_lock_dest;
-	DECLARE_BITMAP(retry_bitmap, IPCMNI);
-
-	bitmap_zero(retry_bitmap, IPCMNI);
-	retry = use_bitmap = shm_lock_dest = 0;
-#endif
+	int id;
+	char sem_held = 0;
 
 	icssvr_nodedown_svc_wait(node, cluster_ipc_svc);
 
-#ifdef IPC_SHM_RACE_FIX
 	write_lock(&cfs_shm_node_mnts_lock);
-	mnt = mntget(cfs_shm_node_mnts[node]);
+	mnt = cfs_shm_node_mnts[node];
 	cfs_shm_node_mnts[node] = NULL;
 	write_unlock(&cfs_shm_node_mnts_lock);
 	mntput(mnt);
 
-	sem_held = !down_trylock(&ids->sem);
-	max_id = sem_held ? ids->max_id : shm_ctlmni;
-
-	SSI_ASSERT(max_id < IPCMNI);
-	last_id = max_id;
-again:
- 	for (id = 0; id <= max_id; id++) {
-		if (use_bitmap && !test_bit(id, retry_bitmap)) {
-			id = find_next_bit(retry_bitmap, max_id+1, id+1);
-			if (id > max_id)
-				break;
+	/* Don't wait for shm_ids.sem since we may deadlock with
+	 * a SHM segment with SHM_LOCK_DEST flag.
+	 */
+	if (down_trylock(&ids->sem)) {
+		if ((id = ids->lock_dest_id) != -1) {
+			/* segment being destroyed by remote server */
+			shp = shm_lock(id);
+			if (shp && shp->shm_node == node &&
+			    (shp->shm_flags & SHM_LOCK_DEST))
+				sem_held = 1;
+			shm_unlock(shp);
 		}
+	} else
+		sem_held = 1;
+
+ 	for (id = 0; id <= ids->max_id; id++) {
 		shp = shm_lock(id);
 		if (!shp)
 			continue;
@@ -1561,25 +1557,10 @@
 			shm_unlock(shp);
 			continue;
 		}
-		if (!sem_held) {
-			/* SSI_XXX: Could be faster if we tracked the ID */
-			if (shp->shm_flags & SHM_LOCK_DEST) {
-				if (last_id > id)
-					last_id = id;
-				shm_lock_dest = 1;
-				sem_held = 1;
-			} else
-				sem_held = !down_trylock(&ids->sem);
-		}
 		if (shp->shm_nattch == 0) {
 			if (!sem_held) {
-				if (!(shp->shm_flags & SHM_DEST))
-					shp->shm_flags |= SHM_DEST;
-				shm_unlock(shp);
-				__set_bit(id, retry_bitmap);
-				if (!retry)
-					retry = 1;
-				continue; /* looking for SHM_LOCK_DEST */
+				down(&ids->sem);
+				sem_held = 1;
 			}
 			SSI_ASSERT(shp->id == id);
 			ssi_local_destroy(shp);
@@ -1590,28 +1571,15 @@
 			shm_unlock(shp);
 		}
 	}
-	if (retry) {
-		retry = 0;
-		if (shm_lock_dest) {
-			/* SHM_LOCK_DEST flag encountered.
-			 * ids->sem was held the whole time
-			 * so our retry_bitmap is accurate.
-			 */
-			SSI_ASSERT(sem_held);
-			if (last_id == 0)
-				goto out;
-			max_id = last_id - 1;
-			use_bitmap = 1;
-		} else if (!sem_held) {
-			down(&ids->sem);
-			sem_held = 1;
-		}
-		goto again;
-	}
-out:
 	if (sem_held)
 		up(&ids->sem);
 #else /* IPC_SHM_RACE_FIX */
+	struct ipc_ids *ids = &shm_ids;
+	struct shmid_kernel *shp;
+	int id;
+
+	icssvr_nodedown_svc_wait(node, cluster_ipc_svc);
+
  	for (id = 0; id <= ids->max_id; id++) {
 		if(ids->entries->p[id] == NULL)
 			continue;

Index: util.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/ipc/util.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- util.c	5 Mar 2010 06:30:21 -0000	1.11
+++ util.c	7 Mar 2010 05:40:14 -0000	1.12
@@ -75,6 +75,11 @@
 		 else
 		 	ids->seq_max = seq_limit;
 	}
+#ifdef CONFIG_SSI
+#ifdef IPC_SHM_RACE_FIX
+	ids->lock_dest_id = -1;
+#endif
+#endif
 
 	ids->entries = ipc_rcu_alloc(sizeof(struct kern_ipc_perm *)*size +
 				     sizeof(struct ipc_id_ary));
@@ -229,6 +234,15 @@
 	if (table)
 		up(&ids->sem);
 }
+
+#ifdef IPC_SHM_RACE_FIX
+/* Called with ids.sem held */
+void
+ipc_set_lock_dest(struct ipc_ids *ids, int id)
+{
+	ids->lock_dest_id = id; /* entry with SHM_LOCK_DEST flag */
+}
+#endif
 #endif /* CONFIG_SSI */
 
 /**


------------------------------------------------------------------------------
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