[SSI] openssi/kernel/cluster/ssi/cfs cfs_ipcshm.c, 1.23, 1.24 cfsproc.c, 1.36, 1.37
Roger Tsang <[email protected]> Fri, 05 Mar 2010 06:30:23 +0000
| Newsgroups | gmane.linux.cluster.ssic.cvs |
|---|---|
| Message-ID | <[email protected]> |
Update of /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs
In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv9483/kernel/cluster/ssi/cfs
Modified Files:
Tag: OPENSSI-FC
cfs_ipcshm.c cfsproc.c
Log Message:
IPC:
- Fix partially initialized shmid_kernel_svr.shm_perm structure.
- Fix ipc/sem.c:exit_sem() GCC warning: ISO C90 forbids mixed declarations and
code.
- Split ssi_shm_setup() into separate functions ssi_shm_setup_client/new() to
reduce stack usage in some paths.
IPC (#ifdef IPC_SHM_RACE_FIX):
- Fix shm_svr_rmid() called without spinlock for the ID.
- Fix race deferencing invalid struct shmid_kernel, shmid_kernel_svr.
- Enable lockfree shmid_kernel_svr IPC id lookup. Use ipc_rcu_alloc and IPC
reference counting.
- Reduce contention. Avoid the ipc_ids mutex. Use per IPC id spinlock.
- Fix cli_ipcname_findid() race with cli_ipcname_getid() could overwrite
existing IPC segment.
- Fix non-critical section under shm_ids.sem lock in shm_create_cli_entry().
- Prevent re-acquire shm_ids.sem in shm_destroy() path. ripc_shm_rmid() no
longer returns with shm_ids.sem unlocked.
- Remove contention in shmem_svr_lookup(); no longer acquire shm_ids_svr.sem.
- Fix do_shmat() possible hang calling dput() while holding spinlock.
- Fix cfs_shm_node_mnts[] race.
- Fix inode leak in ssi_shm_setup() error path when do_shm_register() fails.
IPC (#ifdef IPC_SHM_LOCK_DEST_FIX):
- Fix [ ssic-linux-Bug 2838006 ] Corrupt SHM_LOCK_DEST flag.
- Refactor ipc_shm_nodedown() for SHM_LOCK_DEST flag. Use SHM_LOCK_DEST flag.
- Fix ripc_drop_locks() error path dereferencing NULL pointer in
ipc_drop_locks().
IPC (#ifdef CFS_IPCSHM_DENTRY):
- ssi_shm_setup_client() use d_instantiate_unique() to prevent duplicate
entries.
cluster/ssi/cfs/cfs_ipcshm.c | 422 ++++++++++++++++++-----------
cluster/ssi/cfs/cfsproc.c | 6
cluster/ssi/ipc/ipcshm_svr.c | 280 +++++++++++--------
cluster/ssi/ipc/namesvr_func.c | 12
cluster/ssi/vproc/reopen.c | 30 +-
include/cluster/ssi/cfs/cfs_fs.h | 16 +
include/cluster/ssi/ipc/shm.h | 13
include/linux/shm.h | 7
ipc/msg.c | 6
ipc/sem.c | 17 -
ipc/shm.c | 450 ++++++++++++++++++++-----------
ipc/util.c | 18 -
ipc/util.h | 5
mm/shmem.c | 9
14 files changed, 845 insertions(+), 446 deletions(-)
Index: cfs_ipcshm.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/cfs_ipcshm.c,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -d -r1.23 -r1.24
--- cfs_ipcshm.c 5 Mar 2010 06:25:36 -0000 1.23
+++ cfs_ipcshm.c 5 Mar 2010 06:30:21 -0000 1.24
@@ -43,15 +43,13 @@
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;
struct vfsmount *cfs_shm_node_mnts[NSC_MAX_NODE_VALUE + 1];
+#ifdef IPC_SHM_RACE_FIX
+DEFINE_RWLOCK(cfs_shm_node_mnts_lock);
+#endif
void
cfs_shm_init(void)
@@ -73,175 +71,273 @@
int shmflg)
{
struct shmid_kernel_svr *svr_shm;
- nsc_nodelist_t *nl;
- int err = 0;
-
- svr_shm = (struct shmid_kernel_svr *)kmalloc(sizeof(*svr_shm),
- GFP_KERNEL);
+#ifdef IPC_SHM_RACE_FIX
+ svr_shm = ipc_rcu_alloc(sizeof(*svr_shm));
+#else
+ svr_shm = (typeof(svr_shm)) kmalloc(sizeof(*svr_shm), GFP_KERNEL);
+#endif
if (!svr_shm)
return -ENOMEM;
- 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);
svr_shm->shm_perm.uid = current->euid;
- svr_shm->shm_perm.cuid = current->euid;
svr_shm->shm_perm.gid = current->egid;
+ svr_shm->shm_perm.cuid = current->euid;
svr_shm->shm_perm.cgid = current->egid;
+ svr_shm->shm_perm.mode = (shmflg & S_IRWXUGO);
svr_shm->shm_perm.seq = shp->shm_perm.seq;
- /* shm_unlock(svr_shm); */
+ svr_shm->shm_perm.local_view = ssi_get_localview();
+ svr_shm->shm_perm.security = NULL;
- nl = NSC_NODELIST_ALLOC();
- NSC_NODELIST_SET1(nl, this_node);
- svr_shm->shm_nodelist = nl;
- svr_shm->shm_svr =(struct svrcfstok *)makehp(cfs_shm_sb,
+ svr_shm->shm_id = newid;
+ svr_shm->shm_segsz = size;
+ svr_shm->shm_cprid = current->pid;
+
+ svr_shm->shm_nodelist = NSC_NODELIST_ALLOC();
+ NSC_NODELIST_SET1(svr_shm->shm_nodelist, this_node);
+
+ svr_shm->shm_svr = (struct svrcfstok *) makehp(cfs_shm_sb,
ssidev_get_s_ssidev(shm_mnt->mnt_sb, FALSE),
shp->shm_file->f_dentry);
- SSI_ASSERT(svr_shm->shm_svr);
+ BUG_ON(!svr_shm->shm_svr);
+
if (shm_svr_addid(svr_shm) < 0) {
- printk("failed to add shm svr\n");
+ printk(KERN_WARNING "%s:failed to add shm svr\n", __FUNCTION__);
HASH_RELE(svr_shm->shm_svr);
- NSC_NODELIST_FREE(nl);
+ NSC_NODELIST_FREE(svr_shm->shm_nodelist);
+#ifdef IPC_SHM_RACE_FIX
+ ipc_rcu_putref(svr_shm);
+#else
kfree(svr_shm);
- err = -EINVAL;
+#endif
+ return -EINVAL;
}
- return err;
+
+ return 0;
}
-struct dentry *
-ssi_shm_setup(clusternode_t server, long newid, int new, key_t key)
+/* Server is remote */
+static struct dentry *
+ssi_shm_setup_client(clusternode_t server, long newid, key_t key)
{
- int status = 0;
- struct shmid_kernel_svr *shmsvr = NULL;
- struct inode *ip = NULL;
- struct qstr this;
+ struct cfs_nettok res_toks[CFS_NTOKS];
+ struct cfsdiropres res;
+ struct cfslookargs args;
+ struct cfs_server dummy;
+ struct super_block *cfs_node_sb;
+ struct inode *ip;
struct dentry *de;
+#ifdef CFS_IPCSHM_DENTRY
+ struct dentry *alias;
+#endif
+ struct qstr this;
+ key_t getkey;
+ int get_remote, size, status = 0;
+ char name[13];
+#ifdef IPC_SHM_RACE_FIX
+ struct vfsmount *mnt;
+ char locked = 0;
+static DECLARE_MUTEX(ssi_shm_setup_lock);
+#endif
- if (server == this_node) {
- if (!new) {
- struct shmid_kernel *shmsvr = shm_cli_get(newid);
- if (!shmsvr)
- return NULL;
- if (shmsvr->shm_file->f_op != &cfs_shm_file_operations)
- printk("shmid %ld not cfs file op yet\n",newid);
- de = dget(shmsvr->shm_file->f_dentry);
- return de;
- }
+ get_remote = (cfs_shm_node_mnts[server] == NULL);
+ if (get_remote) {
#ifdef IPC_SHM_RACE_FIX
- ipc_get_locks(0, &shm_ids_svr, 1);
+ down(&ssi_shm_setup_lock);
+ locked = 1;
+
+ if (cfs_shm_node_mnts[server])
+ goto mounted; /* lost race */
+
+ /* Server will callback to mount remote SHM filesystem
+ * and populate cfs_shm_node_mnts[server] on this node.
+ */
#endif
- shmsvr = (struct shmid_kernel_svr *)shm_svr_get(newid);
- if (!shmsvr) {
+ status = do_shm_server_mount(server, this_node, newid,
+ &getkey, &size);
+ if (status) {
#ifdef IPC_SHM_RACE_FIX
- ipc_drop_locks(0, NULL, &shm_ids_svr, 1);
+ up(&ssi_shm_setup_lock);
#endif
return NULL;
}
- ip = cfs_hpget(cfs_shm_sb, shmsvr->shm_svr);
- if (ip == NULL) {
+
+ key = getkey;
+#ifdef NOTYET
+ sprintf(ssidev_buf, "%8.8x", ssidev);
+ mnt = do_kern_mount("cfs", 0, ssidev_buf, NULL);
+ cfs_shm_node_mnts[server] = mnt->mnt_sb;
+#endif
+
+ }
#ifdef IPC_SHM_RACE_FIX
- ipc_drop_locks(0, NULL, &shm_ids_svr, 1);
+mounted:
+ read_lock(&cfs_shm_node_mnts_lock);
+ mnt = mntget(cfs_shm_node_mnts[server]);
+ read_unlock(&cfs_shm_node_mnts_lock);
+ if (locked)
+ up(&ssi_shm_setup_lock);
+ if (!mnt)
+ return NULL; /* Lost race with nodedown */
+
+ cfs_node_sb = mnt->mnt_sb;
+#else
+ cfs_node_sb = (cfs_shm_node_mnts[server])->mnt_sb;
#endif
- return NULL;
- }
- memcpy(&this, &(shmsvr->shm_svr->sct_dp->d_name), sizeof(struct qstr));
+ dummy.mi_server = server;
+
+ sprintf(name, "SYSV%08x", key);
+ this.name = name;
+ this.len = strlen(name);
+ this.hash = 0;
+ res.cdr_res_toks = res_toks;
+ args.clua_fhandle = *itocfh(cfs_node_sb->s_root->d_inode);
+ args.clua_name = this;
+ cfstok_get_agent(&args.clua_agent);
+
+ status = rcfscall(&dummy, CFSD_PROC_LOOKUP,
+ (xdrproc_t)xdr_cfslookargs, (caddr_t)&args,
+ (xdrproc_t)xdr_cfsdiropres, (caddr_t)&res);
+ if (!status)
+ status = res.cdr_status;
+ if (!status) {
+ ip = cfs_fhget(cfs_node_sb, &(res.cdr_cdrok));
+ /* SSI_ASSERT(ip != NULL); */
+
+ status = do_shm_register(server, this_node,newid,&size);
+ if (status) {
#ifdef IPC_SHM_RACE_FIX
- ipc_drop_locks(0, NULL, &shm_ids_svr, 1);
+ iput(ip);
+ mntput(mnt);
#endif
- de = d_alloc(cfs_shm_sb->s_root, &this);
+ return NULL;
+ }
+
+ de = d_alloc(cfs_node_sb->s_root, &this);
#ifdef CFS_IPCSHM_DENTRY
if (!de) {
iput(ip);
+#ifdef IPC_SHM_RACE_FIX
+ mntput(mnt);
+#endif
return NULL;
}
- d_add(de, ip);
-#else
+ ip->i_size = size;
+
+ alias = d_instantiate_unique(de, ip);
+ if (alias) {
+ dput(de);
+ de = alias;
+ }
+#else /* CFS_IPCSHM_DENTRY */
de->d_sb = ip->i_sb;
- de->d_parent = cfs_shm_sb->s_root;
+ de->d_parent = cfs_node_sb->s_root;
+ ip->i_size = size;
d_instantiate(de, ip);
- d_rehash(shmsvr->shm_svr->sct_dp);
+#endif /* !CFS_IPCSHM_DENTRY */
+#ifdef JUNK
+ shp->shm_file->f_dentry = de;
+ shp->shm_file->f_op = &cfs_shm_file_operations;
+ dput(newde);
+#endif
+#ifdef IPC_SHM_RACE_FIX
+ mntput(mnt);
#endif
return de;
}
- else {
- struct cfs_nettok res_toks[CFS_NTOKS];
- struct cfsdiropres res;
- struct cfslookargs args;
- int get_remote;
- struct super_block *cfs_node_sb;
- struct cfs_server dummy;
- key_t getkey;
- int size;
- char name[13];
-
- get_remote = (cfs_shm_node_mnts[server] == NULL);
- if (get_remote) {
- status = do_shm_server_mount(server, this_node, newid,
- &getkey, &size);
- if (status)
- return NULL;
+ return NULL;
+}
- key = getkey;
-#ifdef NOTYET
- sprintf(ssidev_buf, "%8.8x", ssidev);
- mnt = do_kern_mount("cfs", 0, ssidev_buf, NULL);
- cfs_shm_node_mnts[server] = mnt->mnt_sb;
+static struct dentry *
+ssi_shm_setup_new(long newid)
+{
+ struct qstr this;
+ struct inode *ip;
+ struct dentry *de;
+ struct shmid_kernel_svr *shmsvr;
+#ifdef CFS_IPCSHM_DENTRY
+ struct dentry *res;
#endif
+#ifdef IPC_SHM_RACE_FIX
+ struct svrcfstok *hp;
- }
- cfs_node_sb = (cfs_shm_node_mnts[server])->mnt_sb;
- dummy.mi_server = server;
-
- sprintf(name, "SYSV%08x", key);
- this.name = name;
- this.len = strlen(name);
- this.hash = 0;
- res.cdr_res_toks = res_toks;
- args.clua_fhandle = *itocfh(cfs_node_sb->s_root->d_inode);
- args.clua_name = this;
- cfstok_get_agent(&args.clua_agent);
+ shmsvr = shm_svr_lock(newid);
+ if (!shmsvr)
+ return NULL;
+ hp = shmsvr->shm_svr;
+ HASH_HOLD(hp);
+ shm_svr_unlock(shmsvr);
- status = rcfscall(&dummy, CFSD_PROC_LOOKUP,
- (xdrproc_t)xdr_cfslookargs, (caddr_t)&args,
- (xdrproc_t)xdr_cfsdiropres, (caddr_t)&res);
- if (!status)
- status = res.cdr_status;
- if (!status) {
- ip = cfs_fhget(cfs_node_sb, &(res.cdr_cdrok));
- SSI_ASSERT(ip != NULL);
-
- status = do_shm_register(server, this_node,newid,&size);
- if (status)
- return NULL;
+ ip = cfs_hpget(cfs_shm_sb, hp);
+ if (ip == NULL) {
+ HASH_RELE(hp);
+ return NULL;
+ }
+ memcpy(&this, &hp->sct_dp->d_name, sizeof(struct qstr));
+ HASH_RELE(hp);
+#else
+ shmsvr = (struct shmid_kernel_svr *)shm_svr_get(newid);
+ if (!shmsvr)
+ return NULL;
+ ip = cfs_hpget(cfs_shm_sb, shmsvr->shm_svr);
+ if (ip == NULL)
+ return NULL;
+ memcpy(&this, &shmsvr->shm_svr->sct_dp->d_name, sizeof(struct qstr));
+#endif /* !IPC_SHM_RACE_FIX */
- de = d_alloc(cfs_node_sb->s_root, &this);
+ de = d_alloc(cfs_shm_sb->s_root, &this);
#ifdef CFS_IPCSHM_DENTRY
- if (!de) {
- iput(ip);
- return NULL;
- }
+ if (!de) {
+ iput(ip);
+ return NULL;
+ }
+
+ res = d_add_unique(de, ip);
+ if (res) {
+ dput(de);
+ de = res;
+ }
#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;
- shp->shm_file->f_op = &cfs_shm_file_operations;
- dput(newde);
+ de->d_sb = ip->i_sb;
+ de->d_parent = cfs_shm_sb->s_root;
+ d_instantiate(de, ip);
+ d_rehash(shmsvr->shm_svr->sct_dp);
+#endif /* !CFS_IPCSHM_DENTRY */
+ return de;
+}
+
+struct dentry *
+ssi_shm_setup(clusternode_t server, long newid, int new, key_t key)
+{
+ struct shmid_kernel *shp;
+ struct dentry *de;
+
+ if (server != this_node)
+ return ssi_shm_setup_client(server, newid, key);
+
+ /* SSI_ASSERT(server == this_node); */
+ if (new)
+ return ssi_shm_setup_new(newid);
+
+#ifdef IPC_SHM_RACE_FIX
+ shp = shm_cli_lock(newid);
+#else
+ shp = shm_cli_get(newid);
#endif
- return de;
- }
- }
+ if (!shp)
+ return NULL;
- return NULL;
+ if (shp->shm_file->f_op != &cfs_shm_file_operations) {
+ printk(KERN_WARNING "%s: shmid %ld not "
+ "cfs file op yet\n", __FUNCTION__, newid);
+ }
+ de = dget(shp->shm_file->f_dentry);
+#ifdef IPC_SHM_RACE_FIX
+ shm_cli_unlock(shp);
+#endif
+ return de;
}
static struct super_block *
@@ -307,7 +403,28 @@
HASH_RELE(shmsvr->shm_svr);
}
-/* Caller must hold shm_ids.sem or shm_ids_svr.sem */
+#ifdef IPC_SHM_RACE_FIX
+struct inode *
+shm_svr_grab_inode(int id)
+{
+ struct shmid_kernel_svr *shmsvr;
+ struct inode *inode;
+
+ shmsvr = shm_svr_lock(id);
+ if (!shmsvr)
+ return NULL;
+ inode = shmsvr->shm_svr->sct_ip;
+ if (inode)
+ atomic_inc(&inode->i_count);
+ shm_svr_unlock(shmsvr);
+ return inode;
+}
+#endif /* IPC_SHM_RACE_FIX */
+
+/*
+ * Caller must hold shm_ids.sem or shmid_kernel_svr->shm_perm.lock
+ * if dereferencing returned inode. Otherwise use shm_svr_grab_inode().
+ */
struct inode *
shm_svr_get_inode(int id)
{
@@ -340,17 +457,13 @@
return ERR_PTR(error);
#ifdef IPC_SHM_RACE_FIX
- ipc_get_locks(0, &shm_ids_svr, 1);
-#endif
+ inode = shm_svr_grab_inode(id);
+ if (!inode)
+ return ERR_PTR(-EACCES);
+#else
inode = shm_svr_get_inode(id);
- if (!inode || !igrab(inode)) {
-#ifdef IPC_SHM_RACE_FIX
- ipc_drop_locks(0, NULL, &shm_ids_svr, 1);
-#endif
+ if (!inode || !igrab(inode))
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);
@@ -361,20 +474,31 @@
{
int i;
- if (!strncmp(de->d_name.name, "SYSV", 4)) {
- 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 (de->d_sb == (cfs_shm_node_mnts[i])->mnt_sb)
- return 1;
+ if (strncmp(de->d_name.name, "SYSV", 4))
+ return 0;
+
+ 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);
+ }
+#ifdef IPC_SHM_RACE_FIX
+ read_lock(&cfs_shm_node_mnts_lock);
+#endif
+ for (i=1; i <= (NSC_MAX_NODE_VALUE + 1); i++) {
+ if (!cfs_shm_node_mnts[i])
+ continue;
+ if (de->d_sb == (cfs_shm_node_mnts[i])->mnt_sb) {
+#ifdef IPC_SHM_RACE_FIX
+ read_unlock(&cfs_shm_node_mnts_lock);
+#endif
+ return 1;
}
}
-
+#ifdef IPC_SHM_RACE_FIX
+ read_unlock(&cfs_shm_node_mnts_lock);
+#endif
return 0;
}
Index: cfsproc.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/cfsproc.c,v
retrieving revision 1.36
retrieving revision 1.37
diff -u -d -r1.36 -r1.37
--- cfsproc.c 17 Dec 2009 06:43:50 -0000 1.36
+++ cfsproc.c 5 Mar 2010 06:30:21 -0000 1.37
@@ -1310,7 +1310,13 @@
data.payload = argp;
sprintf(ssidev_buffer, "%8.8x", argp->ssidev);
mnt = do_kern_mount("cfs", 0, ssidev_buffer, &data);
+#ifdef IPC_SHM_RACE_FIX
+ write_lock(&cfs_shm_node_mnts_lock);
+ cfs_shm_node_mnts[argp->server] = mnt;
+ write_unlock(&cfs_shm_node_mnts_lock);
+#else
cfs_shm_node_mnts[argp->server] = mnt;
+#endif
return;
}
------------------------------------------------------------------------------
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