[SSI] openssi/kernel/ipc shm.c, 1.33, 1.34 util.c, 1.12, 1.13 util.h, 1.14, 1.15
Roger Tsang <[email protected]> Mon, 29 Mar 2010 06:17:02 +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-serv16378/kernel/ipc
Modified Files:
Tag: OPENSSI-FC
shm.c util.c util.h
Log Message:
IPC:
- Optimize away redundant initialization in newseg() and do_ssi_shm_noclients().
- Initialize shm_node inside newseg(). Optimize away shm_un/lock() dance.
- Test shm_sem_owned() shm_ids.sem semaphore in ssi_shm_noclients().
- Fix shmctl(IPC_RMID) was not setting SHM_DEST flag on other clients in the cluster.
- Fix IPC id 0 race. ipc_get_locks() / ipc_drop_locks() skipped id 0.
IPC (#ifdef IPC_SHM_RACE_FIX):
- Fix shm_svr_addid() array bounds violation when /proc/sys/kernel/shmmni is greater than 4096 (SHMNMI).
- Fix dereferencing invalid shm_kernel_svr structure after calling ssi_shm_noclients().
- Fix do_ssi_shm_noclients() remote clients did not wait for server to failover.
cluster/ssi/ipc/ipcmsg_svr.c | 4
cluster/ssi/ipc/ipcsem_svr.c | 4
cluster/ssi/ipc/ipcshm_svr.c | 114 +++++++------
cluster/ssi/ipc/namesvr_func.c | 8
include/cluster/ssi/ipc/shm.h | 3
ipc/shm.c | 281 ++++++++++++++++++---------------
ipc/util.c | 9 -
ipc/util.h | 2
8 files changed, 235 insertions(+), 190 deletions(-)
Index: util.h
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/ipc/util.h,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- util.h 7 Mar 2010 05:40:14 -0000 1.14
+++ util.h 29 Mar 2010 06:17:00 -0000 1.15
@@ -86,7 +86,7 @@
extern int ipc_idtoidx(struct ipc_ids* ids, int id);
extern int ssi_get_localview(void);
extern struct kern_ipc_perm *ipc_get_locks(int, struct ipc_ids *, int);
-extern void ipc_drop_locks(int, struct kern_ipc_perm *, struct ipc_ids *, int);
+extern void ipc_drop_locks(struct kern_ipc_perm *, struct ipc_ids *);
extern void __init ssi_ipc_nodehint_init(clusternode_t **, int *, int, int);
extern void *ssi_ipc_nodehint_realloc(clusternode_t **, int *, int *, int *);
extern int ipc_grow_ary(struct ipc_ids *, int);
Index: shm.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/ipc/shm.c,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -d -r1.33 -r1.34
--- shm.c 21 Mar 2010 05:33:50 -0000 1.33
+++ shm.c 29 Mar 2010 06:17:00 -0000 1.34
@@ -47,7 +47,9 @@
struct vm_operations_struct cfs_shm_vm_ops;
struct ipc_ids shm_ids_svr;
+#ifndef IPC_SHM_RACE_FIX
int shmsvrsz = SHMMNI;
+#endif
#endif /* CONFIG_SSI */
#define shm_flags shm_perm.mode
@@ -60,7 +62,7 @@
static struct vm_operations_struct shm_vm_ops;
static struct ipc_ids shm_ids;
-#endif /* CONFIG_SSI */
+#endif /* !CONFIG_SSI */
#define shm_lock(id) ((struct shmid_kernel*)ipc_lock(&shm_ids,id))
#define shm_unlock(shp) ipc_unlock(&(shp)->shm_perm)
@@ -108,8 +110,12 @@
return ((struct shmid_kernel *)ipc_get(&shm_ids,id));
}
#endif /* !IPC_SHM_RACE_FIX */
+int shm_sem_owned(void)
+{
+ return sem_owned(&shm_ids.sem);
+}
-static int newseg (key_t, int, size_t, struct file *, int, int);
+static int newseg (key_t, int, size_t, struct file *, int, int, clusternode_t);
#else /* CONFIG_SSI */
@@ -118,7 +124,7 @@
#define PRINT_HEADER \
len += sprintf(buffer, " key shmid perms size cpid lpid nattch uid gid cuid cgid atime dtime ctime\n");
static int newseg (key_t key, int shmflg, size_t size);
-#endif /* CONFIG_SSI */
+#endif /* !CONFIG_SSI */
#define shm_buildid(id, seq) \
ipc_buildid(&shm_ids, id, seq)
@@ -136,7 +142,7 @@
int shm_tot; /* total number of shared memory pages */
#else
static int shm_tot; /* total number of shared memory pages */
-#endif /* CONFIG_SSI */
+#endif /* !CONFIG_SSI */
void __init shm_init (void)
{
@@ -278,14 +284,14 @@
int shm_mmap(struct file * file, struct vm_area_struct * vma)
#else
static int shm_mmap(struct file * file, struct vm_area_struct * vma)
-#endif /* CONFIG_SSI */
+#endif /* !CONFIG_SSI */
{
file_accessed(file);
#ifdef CONFIG_SSI
vma->vm_ops = &cfs_shm_vm_ops;
#else
vma->vm_ops = &shm_vm_ops;
-#endif /* CONFIG_SSI */
+#endif /* !CONFIG_SSI */
shm_inc(file->f_dentry->d_inode->i_ino);
return 0;
}
@@ -300,20 +306,20 @@
static struct file_operations shm_file_operations = {
.mmap = shm_mmap
};
-#endif /* CONFIG_SSI */
+#endif /* !CONFIG_SSI */
#ifdef CONFIG_SSI
struct vm_operations_struct cfs_shm_vm_ops = {
#else /* CONFIG_SSI */
static struct vm_operations_struct shm_vm_ops = {
-#endif /* CONFIG_SSI */
+#endif /* !CONFIG_SSI */
.open = shm_open, /* callback for a new vm-area open */
.close = shm_close, /* callback for when the vm-area is released */
#ifdef CONFIG_SSI
.nopage = cfs_shared_nopage,
#else /* CONFIG_SSI */
.nopage = shmem_nopage,
-#endif /* CONFIG_SSI */
+#endif /* !CONFIG_SSI */
#ifdef CONFIG_NUMA
.set_policy = shmem_set_policy,
.get_policy = shmem_get_policy,
@@ -323,10 +329,10 @@
#ifdef CONFIG_SSI
/* Must be called with shm_ids.sem locked */
static int newseg (key_t key, int shmflg, size_t size, struct file *fp,
- int view, int newid)
+ int view, int newid, clusternode_t svrnode)
#else
static int newseg (key_t key, int shmflg, size_t size)
-#endif /* CONFIG_SSI */
+#endif /* !CONFIG_SSI */
{
int error;
struct shmid_kernel *shp;
@@ -386,15 +392,18 @@
#ifdef CONFIG_SSI
shp->shm_perm.local_view = view;
+ shp->shm_node = svrnode;
#else
shp->shm_cprid = current->tgid;
shp->shm_segsz = size;
-#endif /* CONFIG_SSI */
+#endif /* !CONFIG_SSI */
shp->shm_lprid = 0;
shp->shm_atim = shp->shm_dtim = 0;
shp->shm_ctim = get_seconds();
shp->shm_nattch = 0;
+#ifndef CONFIG_SSI
shp->id = shm_buildid(id,shp->shm_perm.seq);
+#endif /* !CONFIG_SSI */
shp->shm_file = file;
file->f_dentry->d_inode->i_ino = shp->id;
if (shmflg & SHM_HUGETLB)
@@ -450,7 +459,7 @@
up(&shm_ids.sem);
return err;
-#endif /* CONFIG_SSI */
+#endif /* !CONFIG_SSI */
}
static inline unsigned long copy_shmid_to_user(void __user *buf, struct shmid64_ds *in, int version)
@@ -571,7 +580,7 @@
}
#else
inode = shp->shm_file->f_dentry->d_inode;
-#endif /* CONFIG_SSI */
+#endif /* !CONFIG_SSI */
if (is_file_hugepages(shp->shm_file)) {
struct address_space *mapping = inode->i_mapping;
@@ -772,7 +781,7 @@
#else
err = -EINVAL;
goto out;
-#endif /* CONFIG_SSI */
+#endif /* !CONFIG_SSI */
}
else if(cmd==SHM_STAT) {
err = -EINVAL;
@@ -803,7 +812,7 @@
tbuf.shm_segsz = shm_get_segsize(shp);
#else
tbuf.shm_segsz = shp->shm_segsz;
-#endif /* CONFIG_SSI */
+#endif /* !CONFIG_SSI */
tbuf.shm_atime = shp->shm_atim;
tbuf.shm_dtime = shp->shm_dtim;
tbuf.shm_ctime = shp->shm_ctim;
@@ -812,15 +821,18 @@
/* NEED to go get creator pid from svr struct */
tbuf.shm_cpid = shm_get_cpid(shp);
/* NEED to go get # of attaches from all clients */
- tbuf.shm_nattch = ssi_shm_noclients(shp, 0, 0, 1);
-#else
+ tbuf.shm_nattch = ssi_shm_noclients(shp, 0);
+#ifndef IPC_SHM_RACE_FIX
+ shm_unlock(shp);
+#endif
+#else /* CONFIG_SSI */
tbuf.shm_cpid = shp->shm_cprid;
if (!is_file_hugepages(shp->shm_file))
tbuf.shm_nattch = shp->shm_nattch;
else
tbuf.shm_nattch = file_count(shp->shm_file) - 1;
-#endif /* CONFIG_SSI */
shm_unlock(shp);
+#endif /* !CONFIG_SSI */
if(copy_shmid_to_user (buf, &tbuf, version))
err = -EFAULT;
else
@@ -903,11 +915,20 @@
goto out_unlock_up;
#ifdef CONFIG_SSI
- if (shp->shm_nattch ||
- ssi_shm_noclients(shp, 1, 1, 1)) {
-#else
- if (shp->shm_nattch){
+ up(&shm_ids.sem);
+ if (ssi_shm_noclients(shp, 1))
+ goto out;
+ down(&shm_ids.sem);
+#ifdef IPC_SHM_RACE_FIX
+ shp = shm_lock(shmid);
+ if (shp == NULL) {
+ /* Lost race while ssi_shm_noclients() slept */
+ err = -EINVAL;
+ goto out_up;
+ }
+#endif
#endif /* CONFIG_SSI */
+ if (shp->shm_nattch){
shp->shm_flags |= SHM_DEST;
/* Do not find it any more */
shp->shm_perm.key = IPC_PRIVATE;
@@ -1057,13 +1078,13 @@
up(&shm_ids.sem);
goto found;
}
- id = newseg(key, flags, size, NULL, ssi_get_localview(), shmid);
+ id = newseg(key, flags, size, NULL,
+ ssi_get_localview(), shmid, svrnode);
if (id < 0) {
up(&shm_ids.sem);
return -EINVAL;
}
shp = shm_lock(shmid);
- shp->shm_node = svrnode;
up(&shm_ids.sem);
}
found:
@@ -1080,7 +1101,7 @@
#else
shm_unlock(shp);
goto out;
-#endif /* CONFIG_SSI */
+#endif /* !CONFIG_SSI */
}
if (ipcperms(&shp->shm_perm, acc_mode)) {
#ifdef CONFIG_SSI
@@ -1090,7 +1111,7 @@
shm_unlock(shp);
err = -EACCES;
goto out;
-#endif /* CONFIG_SSI */
+#endif /* !CONFIG_SSI */
}
err = security_shm_shmat(shp, shmaddr, shmflg);
@@ -1304,7 +1325,7 @@
#else
if ((vma->vm_ops == &shm_vm_ops || is_vm_hugetlb_page(vma)) &&
(vma->vm_start - addr)/PAGE_SIZE == vma->vm_pgoff) {
-#endif /* CONFIG_SSI */
+#endif /* !CONFIG_SSI */
size = vma->vm_file->f_dentry->d_inode->i_size;
@@ -1337,7 +1358,7 @@
#else
if ((vma->vm_ops == &shm_vm_ops || is_vm_hugetlb_page(vma)) &&
(vma->vm_start - addr)/PAGE_SIZE == vma->vm_pgoff)
-#endif /* CONFIG_SSI */
+#endif /* !CONFIG_SSI */
do_munmap(mm, vma->vm_start, vma->vm_end - vma->vm_start);
vma = next;
@@ -1355,7 +1376,17 @@
int shm_svr_addid(struct shmid_kernel_svr *shm_svr)
{
- struct ipc_ids *ids = &shm_ids_svr;
+ int id;
+
+#ifdef IPC_SHM_RACE_FIX
+ down(&shm_ids_svr.sem);
+
+ id = ipc_addid(&shm_ids_svr, &shm_svr->shm_perm,
+ shm_ctlmni, shm_svr->shm_id);
+ if (id != -1)
+ shm_svr_unlock(shm_svr);
+ up(&shm_ids_svr.sem);
+#else /* IPC_SHM_RACE_FIX */
int id = shm_svr->shm_id % SEQ_MULTIPLIER;
struct kern_ipc_perm *new = &(shm_svr->shm_perm);
int size;
@@ -1374,6 +1405,7 @@
ids->seq = 0;
ids->entries->p[id] = new;
up(&shm_ids_svr.sem);
+#endif /* !IPC_SHM_RACE_FIX */
return id;
}
@@ -1442,13 +1474,12 @@
#endif
goto found;
}
- id = newseg(key, flags, sz, file, view, shmid);
+ id = newseg(key, flags, sz, file, view, shmid, svrnode);
if (id < 0) {
up(&shm_ids.sem);
return id;
}
shp = shm_lock(shmid);
- shp->shm_node = svrnode;
#ifdef IPC_SHM_RACE_FIX
up(&shm_ids.sem);
#endif
@@ -1501,18 +1532,15 @@
}
/* create client */
- id = newseg(key, 0, size, NULL, view, shmid);
+ id = newseg(key, 0, size, NULL, view, shmid, svrnode);
+ up(&shm_ids.sem);
if (id < 0) {
- up(&shm_ids.sem);
printk(KERN_WARNING "%s: Unable create new segment %d\n",
__FUNCTION__, shmid);
return -EINVAL;
}
- shp = shm_lock(shmid);
- shp->shm_node = svrnode;
- shm_unlock(shp);
- up(&shm_ids.sem);
return 0;
+
found:
if (shp->id != shmid || shp->shm_perm.key != key ||
shp->shm_node != svrnode) {
@@ -1635,9 +1663,9 @@
up(&shm_ids.sem);
} else {
shp->shm_flags |= SHM_DEST;
- ipc_drop_locks(shp->id,
+ ipc_drop_locks(
(struct kern_ipc_perm *)shp,
- &shm_ids, 1);
+ &shm_ids);
}
}
else {
@@ -1649,8 +1677,8 @@
cli_ipcname_rmid(NAME_SERVICE_SHM, id);
id = 0;
}
- ipc_drop_locks(id, (struct kern_ipc_perm *)shp,
- &shm_ids, 1);
+ ipc_drop_locks((struct kern_ipc_perm *)shp,
+ &shm_ids);
}
}
}
@@ -1751,99 +1779,102 @@
#ifndef IPC_SHM_RACE_FIX
down(&shm_ids.sem);
#endif
- if (!retval) {
- retval = newid;
+ if (retval)
+ goto out_nolock;
+
+ retval = newid;
#ifndef IPC_SHM_DESTROY_FIX
- /*
- * FIXME, fercrissake. Why are we skipping shm_register for client?
- */
- if (server != this_node || !create)
- goto out_nolock;
+ /*
+ * FIXME, fercrissake. Why are we skipping shm_register for client?
+ */
+ if (server != this_node || !create)
+ goto out_nolock;
+#else
+ if (!create)
+ goto out_nolock;
#endif
- /* setup cfs stuff */
- if (server == this_node && create) {
- /* need to setup shm svr structure & cfs svrstruct */
+ /* setup cfs stuff */
+ if (server == this_node) {
+ /* need to setup shm svr structure & cfs svrstruct */
- /* create client */
- id = newseg(key, shmflg, size, NULL,
- ssi_get_localview(), newid);
- if (id < 0) {
- cli_ipcname_rmid(NAME_SERVICE_SHM, newid);
- retval = id;
- goto out_nolock;
- }
- shp = shm_lock(newid);
- shp->shm_node = server;
- shm_unlock(shp);
- /* create and fill server structure */
- if (shm_svr_create(shp, newid, size, key, shmflg) < 0) {
- cli_ipcname_rmid(NAME_SERVICE_SHM, newid);
- shp = shm_lock(newid);
- ssi_local_destroy(shp);
- retval = -EINVAL;
- goto out_nolock;
- }
+ /* create client */
+ id = newseg(key, shmflg, size, NULL,
+ ssi_get_localview(), newid, server);
+ if (id < 0) {
+ cli_ipcname_rmid(NAME_SERVICE_SHM, newid);
+ retval = id;
+ goto out_nolock;
+ }
+ SSI_ASSERT(id == newid);
+ shp = shm_get(newid);
+ /* create and fill server structure */
+ if (shm_svr_create(shp, newid, size, key, shmflg) < 0) {
+ cli_ipcname_rmid(NAME_SERVICE_SHM, newid);
+ shp = shm_lock(newid);
+ ssi_local_destroy(shp);
+ retval = -EINVAL;
+ goto out_nolock;
}
- /* Now setup the cfs stuff for shm client structure */
- /* This is the part where the client has to register with
- * the svr node, and svr node sends back handle, actually
- * server sends back a cfsdirok struct which has the
- * info needed to create the cinode.
- */
- if (create) {
- struct dentry *newde;
+ }
+ /* Now setup the cfs stuff for shm client structure */
+ /* This is the part where the client has to register with
+ * the svr node, and svr node sends back handle, actually
+ * server sends back a cfsdirok struct which has the
+ * info needed to create the cinode.
+ */
+ {
+ struct dentry *newde;
#ifdef IPC_SHM_RACE_FIX
- struct dentry *old_dentry;
+ struct dentry *old_dentry;
- /* go register with server, create cfs stuff */
- newde = ssi_shm_setup(server, newid, size, key);
+ /* go register with server, create cfs stuff */
+ newde = ssi_shm_setup(server, newid, size, key);
- shp = shm_lock(newid);
- if (!shp) {
- dput(newde);
- retval = -ESRCH;
- goto out_nolock;
- }
- if (!newde) {
- shm_destroy(shp);
- retval = -ESRCH;
- goto out_nolock;
- }
+ shp = shm_lock(newid);
+ if (!shp) {
+ dput(newde);
+ retval = -ESRCH;
+ goto out_nolock;
+ }
+ if (!newde) {
+ shm_destroy(shp);
+ retval = -ESRCH;
+ goto out_nolock;
+ }
+
+ /* switch file to cfs and cleanup */
+ old_dentry = shp->shm_file->f_dentry;
+ shp->shm_file->f_dentry = newde;
+ shp->shm_file->f_op = &cfs_shm_file_operations;
+ shp->shm_file->f_mapping = newde->d_inode->i_mapping;
+ shp->shm_node = server;
+ shm_unlock(shp);
+ up(&shm_ids.sem);
+ dput(old_dentry);
+ return retval;
+#else /* IPC_SHM_RACE_FIX */
+ /* go register with server, create cfs stuff */
+ newde = ssi_shm_setup(server, newid, size, key);
+ if (newde) {
/* switch file to cfs and cleanup */
- old_dentry = shp->shm_file->f_dentry;
+ dput(shp->shm_file->f_dentry);
shp->shm_file->f_dentry = newde;
shp->shm_file->f_op = &cfs_shm_file_operations;
- shp->shm_file->f_mapping = newde->d_inode->i_mapping;
+ shp->shm_file->f_mapping =
+ newde->d_inode->i_mapping;
shp->shm_node = server;
- shm_unlock(shp);
- up(&shm_ids.sem);
-
- dput(old_dentry);
- return retval;
-#else /* IPC_SHM_RACE_FIX */
- /* go register with server, create cfs stuff */
- newde = ssi_shm_setup(server, newid, size, key);
- if (newde) {
- /* switch file to cfs and cleanup */
- dput(shp->shm_file->f_dentry);
- shp->shm_file->f_dentry = newde;
- shp->shm_file->f_op = &cfs_shm_file_operations;
- shp->shm_file->f_mapping =
- newde->d_inode->i_mapping;
- shp->shm_node = server;
- }
- else {
- shm_lock(newid);
- shm_destroy(shp);
- retval = -ESRCH;
- goto out_nolock;
- }
-#endif /* !IPC_SHM_RACE_FIX */
}
+ else {
+ shm_lock(newid);
+ shm_destroy(shp);
+ retval = -ESRCH;
+ goto out_nolock;
+ }
+#endif /* !IPC_SHM_RACE_FIX */
}
out_nolock:
up(&shm_ids.sem);
@@ -1886,7 +1917,7 @@
for(i = 0; i <= id_count; i++) {
#else /* CONFIG_SSI */
for(i = 0; i <= shm_ids.max_id; i++) {
-#endif /* CONFIG_SSI */
+#endif /* !CONFIG_SSI */
struct shmid_kernel* shp;
#ifdef CONFIG_SSI
key_t ipc_id;
@@ -1921,7 +1952,7 @@
}
#else
shp = shm_lock(i);
-#endif /* CONFIG_SSI */
+#endif /* !CONFIG_SSI */
if (shp != NULL) {
#ifdef CONFIG_SSI
@@ -1930,7 +1961,7 @@
#else
#define SMALL_STRING "%10d %10d %4o %10u %5u %5u %5d %5u %5u %5u %5u %10lu %10lu %10lu\n"
#define BIG_STRING "%10d %10d %4o %21u %5u %5u %5d %5u %5u %5u %5u %10lu %10lu %10lu\n"
-#endif /* CONFIG_SSI */
+#endif /* !CONFIG_SSI */
char *format;
if (sizeof(size_t) <= sizeof(int))
@@ -1962,7 +1993,7 @@
shp->shm_cprid,
shp->shm_lprid,
is_file_hugepages(shp->shm_file) ? (file_count(shp->shm_file) - 1) : shp->shm_nattch,
-#endif /* CONFIG_SSI */
+#endif /* !CONFIG_SSI */
shp->shm_perm.uid,
shp->shm_perm.gid,
shp->shm_perm.cuid,
@@ -1982,7 +2013,7 @@
kfree(shp);
#else
shm_unlock(shp);
-#endif /* CONFIG_SSI */
+#endif /* !CONFIG_SSI */
pos += len;
if(pos < offset) {
len = 0;
Index: util.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/ipc/util.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- util.c 7 Mar 2010 05:40:14 -0000 1.12
+++ util.c 29 Mar 2010 06:17:00 -0000 1.13
@@ -220,18 +220,17 @@
if (table)
down(&ids->sem);
- if (id>0)
+ if (id != -1)
p = ipc_lock(ids, id);
return p;
}
void
-ipc_drop_locks(int id, struct kern_ipc_perm *perm, struct ipc_ids *ids,
- int table)
+ipc_drop_locks(struct kern_ipc_perm *perm, struct ipc_ids *ids)
{
- if (id > 0)
+ if (perm)
ipc_unlock(perm);
- if (table)
+ if (ids)
up(&ids->sem);
}
------------------------------------------------------------------------------
Download Intel® 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