[SSI] openssi/kernel/cluster/ssi/cfs cfs_ipcshm.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/cfs
In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvs-serv32639/cluster/ssi/cfs

Modified Files:
      Tag: OPENSSI-FC
	cfs_ipcshm.c 
Log Message:
IPC:
- Fix shm_ids_svr table race; mutex not held, wrong mutex held, or releasing unheld mutex. (#ifdef IPC_SHM_RACE_FIX)
- Downgrade NSC_IPC_WRLOCK() where appropriate; reduce contention. (#ifdef NSC_IPC_RWLOCK_DOWNGRADE)

 cluster/ssi/cfs/cfs_ipcshm.c   |   66 +++++++++++++++++++++++++++++------
 cluster/ssi/ipc/ipcshm_svr.c   |   76 ++++++++++++++++++++++++++++++++++-------
 cluster/ssi/ipc/namesvr_func.c |   68 ++++++++++++++++++++++++++++++++++++
 include/linux/config.h         |    1 
 ipc/shm.c                      |    3 +
 5 files changed, 188 insertions(+), 26 deletions(-)


Index: cfs_ipcshm.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/cfs_ipcshm.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- cfs_ipcshm.c	19 Feb 2009 08:01:01 -0000	1.20
+++ cfs_ipcshm.c	24 Feb 2009 01:51:47 -0000	1.21
@@ -43,6 +43,11 @@
 
 extern struct super_block *cfs_shm_sb;
 extern struct vfsmount *shm_mnt;
+#ifdef IPC_SHM_RACE_FIX
+extern struct ipc_ids shm_ids_svr;
+extern void ipc_drop_locks(int, struct kern_ipc_perm *, struct ipc_ids *, int);
+extern struct kern_ipc_perm * ipc_get_locks(int, struct ipc_ids *, int);
+#endif
 static struct super_block *shm_get_cfs_sb(clusternode_t, struct vfsmount *);
 
 struct super_block *cfs_shm_sb;
@@ -80,6 +85,7 @@
 	svr_shm->shm_id = newid;
 	svr_shm->shm_segsz = size;
 	svr_shm->shm_cprid = current->pid;
+
 	svr_shm->shm_perm.key = key;
 	svr_shm->shm_perm.local_view = ssi_get_localview();
 	svr_shm->shm_perm.mode = (shmflg & S_IRWXUGO);
@@ -88,6 +94,8 @@
 	svr_shm->shm_perm.gid = current->egid;
 	svr_shm->shm_perm.cgid = current->egid;
 	svr_shm->shm_perm.seq = shp->shm_perm.seq;
+	/* shm_unlock(svr_shm); */
+
 	nl = NSC_NODELIST_ALLOC();
 	NSC_NODELIST_SET1(nl, this_node);
 	svr_shm->shm_nodelist = nl;
@@ -124,15 +132,33 @@
 			de = dget(shmsvr->shm_file->f_dentry);
 			return de;
 		}
+#ifdef IPC_SHM_RACE_FIX
+		ipc_get_locks(0, &shm_ids_svr, 1);
+#endif
 		shmsvr = (struct shmid_kernel_svr *)shm_svr_get(newid);
-		if (!shmsvr)
+		if (!shmsvr) {
+#ifdef IPC_SHM_RACE_FIX
+			ipc_drop_locks(0, NULL, &shm_ids_svr, 1);
+#endif
 			return NULL;
+		}
 		ip = cfs_hpget(cfs_shm_sb, shmsvr->shm_svr);
-		if (ip == NULL)
+		if (ip == NULL) {
+#ifdef IPC_SHM_RACE_FIX
+			ipc_drop_locks(0, NULL, &shm_ids_svr, 1);
+#endif
 			return NULL;
+		}
 		memcpy(&this, &(shmsvr->shm_svr->sct_dp->d_name), sizeof(struct qstr));
+#ifdef IPC_SHM_RACE_FIX
+		ipc_drop_locks(0, NULL, &shm_ids_svr, 1);
+#endif
 		de = d_alloc(cfs_shm_sb->s_root, &this);
 #ifdef CFS_IPCSHM_DENTRY
+		if (!de) {
+			iput(ip);
+			return NULL;
+		}
 		d_add(de, ip);
 #else
 		de->d_sb = ip->i_sb;
@@ -195,11 +221,16 @@
 				return NULL;
 
 			de = d_alloc(cfs_node_sb->s_root, &this);
-			ip->i_size = size;
-#ifndef CFS_IPCSHM_DENTRY
+#ifdef CFS_IPCSHM_DENTRY
+			if (!de) {
+				iput(ip);
+				return NULL;
+			}
+#else
 			de->d_sb = ip->i_sb;
 			de->d_parent = cfs_node_sb->s_root;
 #endif
+			ip->i_size = size;
 			d_instantiate(de, ip);
 #ifdef JUNK
 			shp->shm_file->f_dentry = de;
@@ -274,6 +305,7 @@
 	HASH_RELE(shmsvr->shm_svr);
 }
 
+/* Caller must hold shm_ids.sem or shm_ids_svr.sem */
 struct inode *
 shm_svr_get_inode(int id)
 {
@@ -300,9 +332,19 @@
 	sscanf(dentry->d_name.name, "SYSV%x", &real_key);
 	cli_ipcname_getid(NAME_SERVICE_SHM, real_key, 0, &id, &svr, 
 						ssi_get_localview(), &size);
+#ifdef IPC_SHM_RACE_FIX
+	ipc_get_locks(0, &shm_ids_svr, 1);
+#endif
 	inode = shm_svr_get_inode(id);
-	if (!inode || !igrab(inode))
+	if (!inode || !igrab(inode)) {
+#ifdef IPC_SHM_RACE_FIX
+		ipc_drop_locks(0, NULL, &shm_ids_svr, 1);
+#endif
 		return ERR_PTR(-EACCES);
+	}
+#ifdef IPC_SHM_RACE_FIX
+	ipc_drop_locks(0, NULL, &shm_ids_svr, 1);
+#endif
 
 	return d_splice_alias(inode, dentry);
 }
@@ -313,16 +355,16 @@
 	int i;
 
 	if (!strncmp(de->d_name.name, "SYSV", 4)) {
-		if (is_pfs && de->d_inode && is_shmem_inode(de->d_inode))
-			return 1;
-
+		if (is_pfs) {
+			if (de->d_inode)
+				return is_shmem_inode(de->d_inode);
+			/* negative lookup */
+			return (de->d_sb == (cfs_shm_node_mnts[this_node])->mnt_root->d_sb);
+		}
 		for (i=1; i <= (NSC_MAX_NODE_VALUE + 1); i++) {
 			if (!cfs_shm_node_mnts[i])
 				continue;
-			if (is_pfs) { /* negative lookup */
-				if (de->d_sb == (cfs_shm_node_mnts[i])->mnt_root->d_sb)
-					return 1;
-			} else if (de->d_sb == (cfs_shm_node_mnts[i])->mnt_sb)
+			if (de->d_sb == (cfs_shm_node_mnts[i])->mnt_sb)
 				return 1;
 		}
 	}


------------------------------------------------------------------------------
Open Source Business Conference (OSBC), March 24-25, 2009, San Francisco, CA
-OSBC tackles the biggest issue in open source: Open Sourcing the Enterprise
-Strategies to boost innovation and cut costs with open source participation
-Receive a $600 discount off the registration fee with the source code: SFAD
http://p.sf.net/sfu/XcvMzF8H
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.