[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