[SSI] openssi/kernel/cluster/ssi/util fifonm.c, 1.9, 1.10 gfs_mount.c, 1.8, 1.9 load_level.c, 1.23, 1.24 nfs_mount.c, 1.12, 1.13 rcopy.c, 1.12, 1.13 rmtfb.c, 1.23, 1.24 rmtsock.c, 1.22, 1.23 ssidev.c, 1.26, 1.27 ssidev_ics.c, 1.14, 1.15 ssipty.c, 1.14, 1.15

Roger Tsang <[email protected]>
Newsgroups gmane.linux.cluster.ssic.cvs
Message-ID <[email protected]>
Update of /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/util
In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvs-serv16224/kernel/cluster/ssi/util

Modified Files:
      Tag: OPENSSI-FC
	fifonm.c gfs_mount.c load_level.c nfs_mount.c rcopy.c rmtfb.c 
	rmtsock.c ssidev.c ssidev_ics.c ssipty.c 
Log Message:
Bug fixes and enhancements. See ChangeLog.


Index: fifonm.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/util/fifonm.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- fifonm.c	19 Feb 2009 08:01:02 -0000	1.9
+++ fifonm.c	27 Oct 2009 03:18:29 -0000	1.10
@@ -54,7 +54,7 @@
 	clusternode_t		server;
 };
 static struct list_head *fifonm_svr_table;
-static DEFINE_RWLOCK(fifonm_svr_lock); 
+static __cacheline_aligned_in_smp DEFINE_RWLOCK(fifonm_svr_lock);
 #define FIFONM_TBLLEN	(PAGE_SIZE / sizeof(struct list_head))
 
 /* rebuild cache */
@@ -64,7 +64,7 @@
 };
 static struct list_head fifonm_cache_list = LIST_HEAD_INIT(fifonm_cache_list);
 static int fifonm_cache_size = 0;
-static DEFINE_SPINLOCK(fifonm_cache_listlock);
+static __cacheline_aligned_in_smp DEFINE_SPINLOCK(fifonm_cache_listlock);
 
 struct fifonm_rebuild_entry {
 	dev_t			ssidev;
@@ -166,8 +166,11 @@
 		svr_entry->ssidev = ssidev;
 		svr_entry->ino = ino;
 		svr_entry->server = node;
+
+		write_lock(&fifonm_svr_lock);
 		list_add(&svr_entry->hash,
 				&fifonm_svr_table[fifonmsvr_hash(ino)]);
+		write_unlock(&fifonm_svr_lock);
 
 		++rbld_entry;
 	}
@@ -184,6 +187,8 @@
 	int error;
 
 	down_write(&fifonm_cache_rebuildlock);
+	/* We skip fifonm_cache_listlock since we have write sem */
+
 	*data_len = fifonm_cache_size * sizeof(*entry);
 	error = -E2BIG;
 	if (*data_len > buffer_len)
@@ -214,14 +219,13 @@
 		clms_subsys_t service,
 		clusternode_t node)
 {
+	struct fifonm_svr_entry *entry, *next;
 	int hash;
 
 	write_lock(&fifonm_svr_lock);
+
 	for (hash = 0; hash < FIFONM_TBLLEN; ++hash) {
-		struct list_head *cur, *next;
-		list_for_each_safe(cur, next, &fifonm_svr_table[hash]) {
-			struct fifonm_svr_entry *entry =
-				list_entry(cur, struct fifonm_svr_entry, hash);
+		list_for_each_entry_safe(entry, next, &fifonm_svr_table[hash], hash) {
 			if (entry->server == node) {
 				list_del(&entry->hash);
 				kfree(entry);
@@ -250,19 +254,18 @@
  * Server routines
  */
 
+/* Caller holds fifonm_svr_lock */
 static inline struct fifonm_svr_entry *
 fifonmsvr_getent(
 	dev_t ssidev,
 	unsigned long ino)
 {
-	struct list_head *cur;
+	struct fifonm_svr_entry *entry;
 
 #ifdef SSI_XXX
 	SSI_ASSERT_LOCKED_SHR_RW_LOCK(&fifonm_svr_lock);
 #endif
-	list_for_each(cur, &fifonm_svr_table[fifonmsvr_hash(ino)]) {
-		struct fifonm_svr_entry *entry =
-			list_entry(cur, struct fifonm_svr_entry, hash);
+	list_for_each_entry(entry, &fifonm_svr_table[fifonmsvr_hash(ino)], hash) {
 		if (entry->ino == ino && entry->ssidev == ssidev)
 			return entry;
 	}
@@ -290,6 +293,7 @@
 
 	*rval = 0;
 	read_lock(&fifonm_svr_lock);
+
 	entry = fifonmsvr_getent(ssidev, ino);
 	if (entry)
 		*svrnode = entry->server;
@@ -312,6 +316,7 @@
 	newentry->server = from_node;
 
 	write_lock(&fifonm_svr_lock);
+
 	entry = fifonmsvr_getent(ssidev, ino);
 	if (entry)
 		*svrnode = entry->server;
@@ -340,6 +345,7 @@
 
 	*rval = 0;
 	write_lock(&fifonm_svr_lock);
+
 	entry = fifonmsvr_getent(ssidev, ino);
 	if (!entry || entry->server != from_node)
 		*rval = -EFNM_BUG;
@@ -390,6 +396,7 @@
 
 repeat:
 	down_read(&fifonm_cache_rebuildlock);
+
 	if (this_node == fifonm_svr)
 		ret = fifonmsvr_getsvr(fifonm_svr, &error, ssidev, ino,
 				this_node, &node);
@@ -406,7 +413,9 @@
 	if (node == this_node) {
 		INIT_LIST_HEAD(&entry->list);
 		entry->inode = inode;
+
 		spin_lock(&fifonm_cache_listlock);
+
 		++fifonm_cache_size;
 		list_add(&entry->list, &fifonm_cache_list);
 		spin_unlock(&fifonm_cache_listlock);
@@ -426,8 +435,7 @@
 {
 	dev_t ssidev = ssidev_get_i_ssidev(inode);
 	unsigned long ino = inode->i_ino;
-	struct list_head *cur;
-	struct fifonm_cache_entry *entry = NULL;
+	struct fifonm_cache_entry *tmp, *entry = NULL;
 	int error, ret;
 
 repeat:
@@ -439,19 +447,18 @@
 		ret = FIFONMSVR_PUTSVR(fifonm_svr, &error, ssidev, ino,
 				this_node);
 	fifonm_rpcerror(0);
-	if (error)
-		BUG();
+	BUG_ON(error);
 
 	spin_lock(&fifonm_cache_listlock);
-	list_for_each(cur, &fifonm_cache_list) {
-		struct fifonm_cache_entry *tmp =
-			list_entry(cur, struct fifonm_cache_entry, list);
+
+	list_for_each_entry(tmp, &fifonm_cache_list, list) {
 		if (tmp->inode == inode) {
 			entry = tmp;
 			break;
 		}
 	}
-	if (!entry) {
+	if (unlikely(!entry)) {
+		spin_unlock(&fifonm_cache_listlock);
 		printk(KERN_CRIT "fifonm_putsvr: entry missing from cache\n");
 		BUG();
 	}

Index: rmtsock.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/util/rmtsock.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- rmtsock.c	24 Mar 2009 04:26:28 -0000	1.22
+++ rmtsock.c	27 Oct 2009 03:18:29 -0000	1.23
@@ -900,10 +900,11 @@
 	}
 #else
 	if (iovlen > 1) {
-		int i;
 		struct iovec *vec = msg->msg_iov;
+		char *__buf;
+		int i;
 
-		if ((int)total_len < 0) {
+		if (total_len > ICS_MAX_OOL_DATA_SIZE) {
 			error = -EMSGSIZE;
 			printk(KERN_ERR "%s: %s: exceeded ics_userbuf "
 					"capacity\n",
@@ -916,11 +917,12 @@
 			goto out;
 		}
 
+		__buf = buf;
 		buflen = 0;
 		for (i = 0; i < msg->msg_iovlen; i++) {
-			copy_from_user(buf, vec->iov_base, vec->iov_len);	
+			copy_from_user(__buf, vec->iov_base, vec->iov_len);
 			buflen += vec->iov_len;
-			buf += vec->iov_len;
+			__buf += vec->iov_len;
 			vec++;
 		}
 	}

Index: load_level.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/util/load_level.c,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -d -r1.23 -r1.24
--- load_level.c	24 Mar 2009 04:26:28 -0000	1.23
+++ load_level.c	27 Oct 2009 03:18:29 -0000	1.24
@@ -35,15 +35,29 @@
 #include <asm/uaccess.h>
 #ifdef CONFIG_MOSIX_LL
 #include <cluster/ssi/mosixll/routines.h>
+#ifdef REXEC_LOADTABLE_RACE_FIX
+#include <cluster/ssi/mosixll/defs.h>
+#include <cluster/ssi/mosixll/balance.h>
+#endif
 #endif
 
 struct loadlvl_register *loadlvl_registered = NULL;
 
 #ifdef CONFIG_LDLVL
+#ifdef REXEC_LOADTABLE_RACE_FIX
+/* array used by master to send load information to other nodes */
+load_array_t *master_load_array; /* protected by loadinfo_lock */
+#ifdef MASTER_LOAD_ARRAY_SEND_SIZE
+clusternode_t master_load_array_max_index; /* protected by loadinfo_lock */
+#endif
+/* number of entries in master_load_array or loadinfo structure for dep nodes */
+atomic_t load_cnt;
+#else
 /* array used by master to send load information to other nodes */
 load_array_t master_load_array[NSC_MAX_NODE_VALUE + 1];
 /* number of entries in master_load_array or loadinfo structure for dep nodes */
 int load_cnt;
+#endif
 
 /* table used to determine whats loadlevelable */
 #ifdef LOADLEVEL_TABLE_LIST
@@ -53,9 +67,18 @@
 #endif
 
 extern clusternode_t clms_master_node;
-int loadlevel_on;
+atomic_t loadlevel_on;
 
+#ifdef REXEC_LOADTABLE_RACE_FIX
+#ifdef REXEC_LOADTABLE_FAST
+clusternode_t *rexec_loadtable;
+#else
+int *rexec_loadtable;
+#endif
+DECLARE_RWSEM(rexec_loadtable_sem);
+#else
 int rexec_loadtable[NSC_MAX_NODE_VALUE + 1];
+#endif
 
 /* Used only for roundrobin exec debugging */
 int ssi_roundrobin;
@@ -63,8 +86,8 @@
 int loadlist_lockinit;
 
 #ifdef CONFIG_MOSIX_LL
-extern struct loadinfo loadinfo[];
-extern int calc_speed(int);
+extern struct loadinfo *loadinfo;
+extern unsigned long calc_speed(unsigned long);
 extern int altload(int, int, int);
 extern void mosix_calc_load(unsigned long);
 int im_ready;
@@ -251,22 +274,50 @@
 void
 initialize_list_lock(void)
 {
+	/* TODO: move these to own function */
+#ifdef CONFIG_MOSIX_LL
+	loadinfo =
+		kzmalloc_nofail(sizeof(*loadinfo) * (NSC_MAX_NODE_VALUE + 1));
+#ifdef DEBUG_MOSIX_LL
+	printk(KERN_NOTICE "%s: loadinfo 0x%p\n", __FUNCTION__, loadinfo);
+#endif
+#endif
+#ifdef REXEC_LOADTABLE_RACE_FIX
+	atomic_set(&load_cnt, 0);
+#ifdef MASTER_LOAD_ARRAY_SEND_SIZE
+	master_load_array_max_index = 0;
+#endif
+	master_load_array =
+		kzmalloc_nofail(sizeof(*master_load_array) * (NSC_MAX_NODE_VALUE + 1));
+	rexec_loadtable =
+		kzmalloc_nofail(sizeof(*rexec_loadtable) * (NSC_MAX_NODE_VALUE + 1));
+#ifdef DEBUG_LDLVL
+	printk(KERN_NOTICE "%s: rexec_loadtable 0x%p\n", __FUNCTION__, rexec_loadtable);
+#endif
+#endif
+
 	LOADLIST_LOCK_INIT();
 	loadlist_lockinit = 1;
 	loadlevel_log_init();
 }
 
 void
-initialize_loadinfo(clusternode_t node, int cpus, int cpupwr)
+initialize_loadinfo(clusternode_t node, int cpus, unsigned long cpupwr)
 {
-
+#ifdef REXEC_LOADTABLE_RACE_FIX
+	write_lock(&loadinfo_lock);
+#endif
 	if (this_node == clms_master_node) {
 		loadinfo[node].node = node;
 	} else
 		loadinfo[node].node = 0;
 
-	if (!cpus || !cpupwr)
+	if (!cpus || !cpupwr) {
+#ifdef REXEC_LOADTABLE_RACE_FIX
+		write_unlock(&loadinfo_lock);
+#endif
 		return;
+	}
 
 #ifdef CONFIG_MOSIX_LL
 	loadinfo[node].ncpus = cpus;
@@ -274,6 +325,13 @@
 #ifdef CONFIG_SSI_LOADINFO_RLOAD
 	loadinfo[node].rload = 0;
 #endif
+#ifdef DEBUG_MOSIX_LL
+	printk(KERN_NOTICE "%s: node=%d ncpus=%d, speed=%lu\n",
+			__FUNCTION__, node, cpus, loadinfo[node].speed);
+#endif
+#endif
+#ifdef REXEC_LOADTABLE_RACE_FIX
+	write_unlock(&loadinfo_lock);
 #endif
 }
 
@@ -282,14 +340,44 @@
  * master.  It will update its loadinfo structure with the new loads
  */
 void
+#ifdef REXEC_LOADTABLE_RACE_FIX
+update_load_info(load_array_t *larray)
+{
+	clusternode_t i, len = larray[0].load;
+#else
 update_load_info(load_array_t *larray, int size)
 {
 	int n, j;
 	int len = size;
 	int index;
+#endif
 
 #ifdef CONFIG_MOSIX_LL
 	/* Cant start load leveling until the node is fully up */
+#ifdef REXEC_LOADTABLE_RACE_FIX
+	if (!im_ready && (clms_get_node_status(this_node) & CLMS_NODE_UP)) {
+		/* initialize the loadinfo structure with the cpu info
+		 * for nodes except myself.  Current node keeps its
+		 * stats in the first entry [0].
+		 */
+		write_lock(&loadinfo_lock);
+		for(i=1; i <= NSC_MAX_NODE_VALUE; i++) {
+			if (i == this_node)
+				continue;
+			loadinfo[i].ncpus = clms.clms_node_info[i].online_cpus;
+			loadinfo[i].speed = calc_speed(clms.clms_node_info[i].cpu_power);
+#ifdef DEBUG_MOSIX_LL
+			if (loadinfo[i].ncpus || loadinfo[i].speed)
+			printk(KERN_NOTICE "%s: node=%d ncpus=%d, speed=%lu\n",
+					__FUNCTION__, i, loadinfo[i].ncpus, loadinfo[i].speed);
+#endif
+		}
+		write_unlock(&loadinfo_lock);
+		if (this_node != clms_master_node)
+			atomic_inc(&load_cnt);
+		im_ready = 1;
+	}
+#else /* !REXEC_LOADTABLE_RACE_FIX */
 	if (!im_ready) {
 		int status;
 
@@ -312,11 +400,52 @@
 	}
 
 	len--; /* dont count myself */
+#endif /* !REXEC_LOADTABLE_RACE_FIX */
 #endif /* CONFIG_MOSIX_LL */
 
-	n = 0;
 	if (!len)
 		return;
+
+#ifdef REXEC_LOADTABLE_RACE_FIX
+#ifdef MASTER_LOAD_ARRAY_SEND_SIZE
+	/* for loop bound by master_load_array_max_index */
+	SSI_ASSERT(len <= NSC_MAX_NODE_VALUE);
+	for(i=1; i <= len; i++) {
+#else
+	for(i=1; i <= NSC_MAX_NODE_VALUE; i++) {
+#endif
+		/* Test: master_load_array[node].node == node */
+		if (i != larray[i].node)
+			continue;
+#ifndef MASTER_LOAD_ARRAY_SEND_SIZE
+		if (!len--)
+			break;
+#endif
+#ifdef CONFIG_MOSIX_LL
+		if (i == this_node)
+			continue;
+#endif /* CONFIG_MOSIX_LL */
+		write_lock(&loadinfo_lock);
+		if (!loadinfo[i].node) {
+			loadinfo[i].node = i;
+			if (this_node != clms_master_node)
+				atomic_inc(&load_cnt);
+		}
+
+#ifdef CONFIG_MOSIX_LL
+#ifdef CONFIG_SSI_LOADINFO_RLOAD
+		loadinfo[i].load = larray[i].load + loadinfo[i].rload;
+#else
+		loadinfo[i].load = larray[i].load;
+#endif
+		loadinfo[i].mem = larray[i].mem;
+#else
+		loadinfo[i].load = larray[i].load;
+#endif /* CONFIG_MOSIX_LL */
+		write_unlock(&loadinfo_lock);
+	}
+#else /* !REXEC_LOADTABLE_RACE_FIX */
+	n = 0;
 	for(j=1; j <= NSC_MAX_NODE_VALUE; j++) {
 		if (larray[j].node) {
 			index = larray[j].node;
@@ -353,13 +482,19 @@
 	/* XXX fall through ? */
 	if (n < len)
 		return;
+#endif /* !REXEC_LOADTABLE_RACE_FIX */
 
 #ifdef CONFIG_MOSIX_LL
 	/* call MOSIX's balancing algorithms */
 	mosix_calc_load(0);
-	if (load_cnt > 1 && loadlevel_on) {
+#ifdef REXEC_LOADTABLE_RACE_FIX
+	if (atomic_read(&load_cnt) > 1 && atomic_read(&loadlevel_on))
+		exec_balance();
+#else
+	if (load_cnt > 1 && atomic_read(&loadlevel_on)) {
 		exec_balance();
 	}
+#endif
 #endif /* CONFIG_MOSIX_LL */
 }
 
@@ -368,29 +503,48 @@
  * dependent node. It updates its load array and loadinfo structure.
  */
 void
-update_load_array(clusternode_t node, unsigned long load, unsigned long mem)
+update_load_array(clusternode_t node, unsigned long *load, unsigned long *mem)
 {
+#ifdef REXEC_LOADTABLE_RACE_FIX
+	if (unlikely(node > NSC_MAX_NODE_VALUE)) {
+		printk("%s: node %d too big\n", __FUNCTION__, node);
+		return;
+	}
+
+	write_lock(&loadinfo_lock);
+#endif
 	if (master_load_array[node].node == 0) {
 		master_load_array[node].node = node;
+#ifdef MASTER_LOAD_ARRAY_SEND_SIZE
+		if (master_load_array_max_index < node)
+			master_load_array_max_index = node;
+#endif
+#ifdef REXEC_LOADTABLE_RACE_FIX
+		atomic_inc(&load_cnt);
+#else
 		load_cnt++;
+#endif
 	}
 
-	master_load_array[node].load = load;
-	master_load_array[node].mem = mem;
+	master_load_array[node].load = *load;
+	master_load_array[node].mem = mem ? *mem : 0;
 
 	/* update loadinfo structure as well */
 #ifdef CONFIG_MOSIX_LL
 	if (node != this_node) {
 #ifdef CONFIG_SSI_LOADINFO_RLOAD
-		loadinfo[node].load = load + loadinfo[node].rload;
+		loadinfo[node].load = *load + loadinfo[node].rload;
 #else
-		loadinfo[node].load = load;
+		loadinfo[node].load = *load;
 #endif
-		loadinfo[node].mem = mem;
+		loadinfo[node].mem = mem ? *mem : 0;
 	}
 #else
-	loadinfo[node].load = load;
-#endif /* CONFIG_MOSIX_LL */
+	loadinfo[node].load = *load;
+#endif /* !CONFIG_MOSIX_LL */
+#ifdef REXEC_LOADTABLE_RACE_FIX
+	write_unlock(&loadinfo_lock);
+#endif
 }
 
 /*
@@ -402,39 +556,90 @@
 loadinfo_received(load_array_t *info)
 {
 	if (this_node == clms_master_node) {
-		update_load_array(info->node, info->load, info->mem);
-#ifdef CONFIG_MOSIX_LL_NOTYET
-		/* call MOSIX's balancing algorithms */
-		if (load_cnt > 1 && loadlevel_on) {
-			load_balance();
-			memory_balance();
-		}
+		update_load_array(info->node, &info->load, &info->mem);
+#ifdef CONFIG_MOSIX_LL
+		mosix_calc_load(0);
 #endif
+	} else
+#ifdef REXEC_LOADTABLE_RACE_FIX
+		update_load_info(info);
+#else
+		update_load_info(info, info[0].load);
+#endif
+#ifdef CONFIG_MOSIX_LL
+	/* call MOSIX's balancing algorithms */
+#ifdef REXEC_LOADTABLE_RACE_FIX
+	if (atomic_read(&load_cnt) > 1 && atomic_read(&loadlevel_on)) {
+#else
+	if (load_cnt > 1 && atomic_read(&loadlevel_on)) {
+#endif
+		load_balance();
+		memory_balance();
 	}
-	else {
-		int cnt;
-
-		cnt = info[0].load;
-		update_load_info(info, cnt);
-	}
-
+#endif
 }
 
 void
 exec_balance(void)
 {
-	register int load; 
-        register struct loadinfo *l;
+        struct loadinfo *l;
+	unsigned long load;
+#ifdef REXEC_LOADTABLE_FAST
+	unsigned int start = 0, i = 1;
+	clusternode_t node;
+
+	/* SSI_ASSERT(NSC_MAX_NODE_VALUE < UINT_MAX); */
+
+	down_write(&rexec_loadtable_sem);
+	node = rexec_loadtable[0] >> NODESHIFT; /* last exec_ll node */
+
+	read_lock_bh(&loadinfo_lock);
+	load = altload(export_load, loadinfo[0].speed, loadinfo[0].ncpus);
+
+	for(l = &loadinfo[1]; l <= &loadinfo[NSC_MAX_NODE_VALUE]; l++) {
+		if(l->node && l->node != this_node &&
+		   l->mem > 0 && l->speed &&
+		   altload(l->load, l->speed, l->ncpus) <= load) {
+			rexec_loadtable[i++] = l->node;
+			/* Find "start" position in rexec_loadtable[] for exec_ll */
+			if (!start && l->node > node)
+				start = i - 1;
+		}
+	}
+	read_unlock_bh(&loadinfo_lock);
+
+	if (i <= NSC_MAX_NODE_VALUE)
+		rexec_loadtable[i] = 0; /* end */
+
+	/* Set "start" position for __ssi_do_execve() */
+	start = start ? : 1;
+	if ((rexec_loadtable[0] & (~0U >> NODESHIFT)) != start)
+		rexec_loadtable[0] = start | (node << NODESHIFT);
 
+	up_write(&rexec_loadtable_sem);
+#else /* !REXEC_LOADTABLE_FAST */
+#ifdef REXEC_LOADTABLE_RACE_FIX
+	down_write(&rexec_loadtable_sem);
+	memset(&rexec_loadtable[1], 0, sizeof(*rexec_loadtable) * NSC_MAX_NODE_VALUE);
+
+	read_lock_bh(&loadinfo_lock);
+	load = altload(export_load, loadinfo[0].speed, loadinfo[0].ncpus);
+#else
 	memset(&rexec_loadtable[1], 0, sizeof(int) * NSC_MAX_NODE_VALUE);
 
 	load = altload(export_load, loadinfo[0].speed, loadinfo[0].ncpus);
+#endif
         for(l = &loadinfo[1]; l < &loadinfo[NSC_MAX_NODE_VALUE+1] ; l++) {
 		if(l->node && l->mem > 0 && l->speed && 
 				altload(l->load, l->speed, l->ncpus) < load) {
 			rexec_loadtable[l->node]++;
 		}
 	}
+#ifdef REXEC_LOADTABLE_RACE_FIX
+	read_unlock_bh(&loadinfo_lock);
+	up_write(&rexec_loadtable_sem);
+#endif
+#endif /* !REXEC_LOADTABLE_FAST */
 }
 
 /*
@@ -444,9 +649,30 @@
 void
 cleanup_loadinfo(clusternode_t node)
 {
+#ifdef REXEC_LOADTABLE_RACE_FIX
+	write_lock(&loadinfo_lock);
+#endif
 	if (master_load_array[node].node != 0) {
+#ifdef REXEC_LOADTABLE_RACE_FIX
+		atomic_dec(&load_cnt);
+		master_load_array[node].node = 0;
+#ifdef MASTER_LOAD_ARRAY_SEND_SIZE
+		if (master_load_array_max_index == node) {
+			clusternode_t i;
+			/* Assign next largest node number */
+			for (i=node-1; i > 0; i--) {
+				if (master_load_array[i].node) {
+					master_load_array_max_index = i;
+					break;
+				}
+			}
+			SSI_ASSERT(i > 0);
+		}
+#endif
+#else
 		master_load_array[node].node = 0;
 		load_cnt--;
+#endif /* !REXEC_LOADTABLE_RACE_FIX */
 		loadinfo[node].node = 0;
 		loadinfo[node].load = 0xffffffff;
 		loadinfo[node].mem = 0;
@@ -454,18 +680,70 @@
 	else if (loadinfo[node].node != 0 && (this_node != clms_master_node)) {
 		loadinfo[node].node = 0;
 		loadinfo[node].load = 0;
+#ifdef REXEC_LOADTABLE_RACE_FIX
+		atomic_dec(&load_cnt);
+#else
 		load_cnt--;
+#endif
 	}
+#ifdef REXEC_LOADTABLE_RACE_FIX
+	write_unlock(&loadinfo_lock);
+#endif
 }
 
 /*
  * Cannot sleep in following path...
- * tasklist_lock	(choose)
+ * tasklist_lock	(choose, mchoose)
  * 			(is_loadlevelable)
  */
 int
 is_loadlevelable(struct task_struct *p, char *fname)
 {
+#ifdef TASK_HOLD_VPROC
+	int ret;
+	struct vproc *vp = p->p_vproc;
+	struct pvproc *pvp;
+	extern int vproc_is_loadlevelable(struct vproc *, char *);
+
+	if (!loadlist_lockinit || (p->exit_state >= EXIT_ZOMBIE) ||
+	    !VPROC_HOLD_AND_CHECK(vp, "is_loadlevelable"))
+		return 0;
+
+	pvp = PVP(vp);
+	if (pvp->pvp_pin || pvp->pvp_localview == 1) {
+		ret = 0;
+		goto out;
+	}
+
+	if (pvp->pvp_loadlevel == 1) {
+		ret = 1;
+		goto out;
+	}
+
+	ret = vproc_is_loadlevelable(vp, fname);
+out:
+	VPROC_RELE(vp, "is_loadlevelable");
+	return ret;
+}
+
+/*
+ * Cannot sleep in following path...
+ * child FLAG LOCK	(vpop_setup_vproc_relations)
+ * 			(vproc_is_loadlevelable)
+ */
+/* May acquire following locks:
+ *	task_lock
+ *	mmap_sem [sem]
+ *	fs->lock
+ *	loadlevellist_lock [sem]
+ *	dcache_lock, d_lock
+ *	sb_lock, s_umount [sem]
+ */
+/* Called with VPROC LOCK or vproc movement or tasklist_lock */
+int
+vproc_is_loadlevelable(struct vproc *vp, char *fname)
+{
+#endif /* TASK_HOLD_VPROC */
 	struct pvproc *pvp;
 	struct inclusion_list *ent;
 	struct mm_struct * mm;
@@ -476,34 +754,53 @@
 	int held;
 #endif
 
-	if (!loadlist_lockinit || (p->exit_state >= EXIT_ZOMBIE) || 
-			!(p->p_vproc) || (p->p_vproc->vp_pid != p->pid))
+#ifdef TASK_HOLD_VPROC
+	if (!loadlist_lockinit || (PVP(vp)->pvp_flag & PV_EXITING) ||
+	    !(PVP(vp)->pvp_flag & PV_IS_LOCAL) ||
+	    (PVP(vp)->pvp_pproc->epid != vp->vp_pid))
+		return 0;
+
+	pvp = PVP(vp);
+#else
+	if (!loadlist_lockinit || (p->exit_state >= EXIT_ZOMBIE) ||
+	    !(p->p_vproc) || (p->p_vproc->vp_pid != p->pid))
 		return 0;
 
 	pvp = PVP(p->p_vproc);
+#endif
 #ifdef LOADLEVEL_TABLE_LIST
 	if (pvp->pvp_pin || pvp->pvp_localview == 1)
 		return 0;
-#else
-	held = VPROC_LOCK_EXCL_HELD(p->p_vproc);
-#endif
 	if (pvp->pvp_loadlevel == -1) {
 		if (!fname) {
+#ifdef TASK_HOLD_VPROC
+			task_t *p = PVP(vp)->pvp_pproc;
+#endif
 			/* Check to see if process has dentry filled in */
-#ifdef LOADLEVEL_TABLE_LIST
-			read_lock_irq(&tasklist_lock);
+			/* RT: Cannot use FLAG LOCK here.
+			 * FLAG LOCK		(pvpop_setsid, pvpop_setctty)
+			 * tasklist_lock	(pproc_setctty)
+			 *
+			 * tasklist_lock	(choose, mchoose)
+			 * 			(is_loadlevelable)
+			 * FLAG LOCK		(vproc_is_loadlevelable)
+			 */
+			/* VPROC_LOCK_FLAG(vp, "is_loadlevelable"); */
+			task_lock(p);
 			dentry = dget(pvp->pvp_comm_de);
 			mnt = mntget(pvp->pvp_comm_mnt);
-			read_unlock_irq(&tasklist_lock);
+			task_unlock(p);
 			if (!dentry) {
 				mntput(mnt);
 				mnt = NULL;
 #else
+	held = VPROC_LOCK_EXCL_HELD(p->p_vproc);
+	if (pvp->pvp_loadlevel == -1) {
+		if (!fname) {
+			/* Check to see if process has dentry filled in */
 			if (PVP(p->p_vproc)->pvp_comm_de) {
-				read_lock_irq(&tasklist_lock);
 				dentry = dget(PVP(p->p_vproc)->pvp_comm_de);
 				mnt = mntget(PVP(p->p_vproc)->pvp_comm_mnt);
-				read_unlock_irq(&tasklist_lock);
 			}
 			else {
 #endif /* !LOADLEVEL_TABLE_LIST */
@@ -515,6 +812,7 @@
 				task_unlock(p);
 				if (!mm)
 					return 0;
+
 				if (!down_read_trylock(&mm->mmap_sem)) {
 					mmput(mm);
 					return 0;
@@ -534,17 +832,14 @@
 			}
 		}
 		else {
-			int error = -ENOENT;
+			int error; /* = -ENOENT; */
 			struct nameidata nd;
 
 			error = path_lookup(fname, LOOKUP_FOLLOW, &nd);
-			if (!error) {
-				dentry = nd.dentry;
-				mnt = nd.mnt;
-			}
-			else
+			if (error)
 				goto out_nolock;
-
+			dentry = nd.dentry;
+			mnt = nd.mnt;
 		}
 
 #ifdef LOADLEVEL_TABLE_LIST
@@ -556,25 +851,24 @@
 				if (dentry == ent->de && mnt == ent->mnt) {
 					LOADLIST_UNLOCK_SHARED();
 					set_mb(pvp->pvp_loadlevel, 1);
-					dput(dentry);
-					mntput(mnt);
-					return 1;
+					goto out_nolock;
 				}
 			}
 			LOADLIST_UNLOCK_SHARED();
 		}
 		set_mb(pvp->pvp_loadlevel, 0);
-	}
-	else if ((pvp->pvp_loadlevel == 0) && fname) {
+	} else if ((pvp->pvp_loadlevel == 0) && fname) {
 		/* reset so that it can be resolved again since process is
 		 * about to exec
 		 */
 		set_mb(pvp->pvp_loadlevel, -1);
 	}
+
 out_nolock:
 	dput(dentry);
 	mntput(mnt);
-	return 0;
+
+	return (pvp->pvp_loadlevel < 0) ? 0 : pvp->pvp_loadlevel;
 #else /* !LOADLEVEL_TABLE_LIST */
 		if (!held)
 			if (!TRY_VPROC_LOCK_EXCL(p->p_vproc,"is_loadlevelable"))

Index: rcopy.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/util/rcopy.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- rcopy.c	3 Feb 2009 06:18:13 -0000	1.12
+++ rcopy.c	27 Oct 2009 03:18:29 -0000	1.13
@@ -96,7 +96,6 @@
 			 pid_t pid, u_long from, char **data, int *data_len)
 {
 	register struct vproc *v = VPROCPTR(pid);
-	struct pvproc *pvp;
 	struct task_struct *p;
 	int copied;
 
@@ -104,14 +103,17 @@
 	SSI_ASSERT(*data_len > 0);
 	SSI_ASSERT(*data_len <= ICS_MAX_OOL_DATA_SIZE);
 	if (v != NULL) {
-		pvp = PVP(v);
-		p = pvp->pvp_pproc;
+		p = PVP(v)->pvp_pproc;
+#ifdef TASK_HOLD_VPROC
+		SSI_ASSERT(PVP(v)->pvp_flag & PV_IS_LOCAL);
+#else
 		SSI_ASSERT(p != NULL);
+#endif
 	}
 	else
 		p = NULL;
 	if (p != NULL) {
-		if (to_node != 0)
+		if (*data == NULL)
 			*data = kmalloc(*data_len, GFP_USER);
 		if (*data != NULL) {
 			copied = access_process_vm(p, from, *data,
@@ -142,7 +144,6 @@
 		       char *data, int data_len)
 {
 	register struct vproc *v = VPROCPTR(pid);
-	struct pvproc *pvp;
 	struct task_struct *p;
 	int copied;
 
@@ -151,9 +152,12 @@
 	SSI_ASSERT(data_len > 0);
 	SSI_ASSERT(data_len <= ICS_MAX_OOL_DATA_SIZE);
 	if (v != NULL) {
-		pvp = PVP(v);
-		p = pvp->pvp_pproc;
+		p = PVP(v)->pvp_pproc;
+#ifdef TASK_HOLD_VPROC
+		SSI_ASSERT(PVP(v)->pvp_flag & PV_IS_LOCAL);
+#else
 		SSI_ASSERT(p != NULL);
+#endif
 	}
 	else
 		p = NULL;
@@ -181,7 +185,6 @@
 				 char **data, int *data_len)
 {
 	register struct vproc *v = VPROCPTR(pid);
-	struct pvproc *pvp;
 	struct task_struct *p;
 	long tmpn;
 
@@ -189,9 +192,12 @@
 	SSI_ASSERT(*data_len > 0);
 	SSI_ASSERT(*data_len <= ICS_MAX_OOL_DATA_SIZE);
 	if (v != NULL) {
-		pvp = PVP(v);
-		p = pvp->pvp_pproc;
+		p = PVP(v)->pvp_pproc;
+#ifdef TASK_HOLD_VPROC
+		SSI_ASSERT(PVP(v)->pvp_flag & PV_IS_LOCAL);
+#else
 		SSI_ASSERT(p != NULL);
+#endif
 	}
 	else
 		p = NULL;
@@ -221,16 +227,18 @@
 			    pid_t pid, u_long from, u_long *n)
 {
 	register struct vproc *v = VPROCPTR(pid);
-	struct pvproc *pvp;
 	struct task_struct *p;
 
 	SSI_ASSERT(v != NULL);
 	SSI_ASSERT(*n > 0);
 	SSI_ASSERT(*n <= ICS_MAX_OOL_DATA_SIZE);
 	if (v != NULL) {
-		pvp = PVP(v);
-		p = pvp->pvp_pproc;
+		p = PVP(v)->pvp_pproc;
+#ifdef TASK_HOLD_VPROC
+		SSI_ASSERT(PVP(v)->pvp_flag & PV_IS_LOCAL);
+#else
 		SSI_ASSERT(p != NULL);
+#endif
 	}
 	else
 		p = NULL;
@@ -252,7 +260,6 @@
 			  pid_t pid, u_long to, u_long *n)
 {
 	register struct vproc *v = VPROCPTR(pid);
-	struct pvproc *pvp;
 	struct task_struct *p;
 	char *cbuf;
 	int copy;
@@ -262,9 +269,12 @@
 	SSI_ASSERT(*n > 0);
 	SSI_ASSERT(*n <= ICS_MAX_OOL_DATA_SIZE);
 	if (v != NULL) {
-		pvp = PVP(v);
-		p = pvp->pvp_pproc;
+		p = PVP(v)->pvp_pproc;
+#ifdef TASK_HOLD_VPROC
+		SSI_ASSERT(PVP(v)->pvp_flag & PV_IS_LOCAL);
+#else
 		SSI_ASSERT(p != NULL);
+#endif
 	}
 	else
 		p = NULL;

Index: rmtfb.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/util/rmtfb.c,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -d -r1.23 -r1.24
--- rmtfb.c	24 Mar 2009 04:26:28 -0000	1.23
+++ rmtfb.c	27 Oct 2009 03:18:29 -0000	1.24
@@ -184,20 +184,29 @@
 rmtfb_set_bit(clusternode_t cli, struct rmtfb_svr *rfb, int set)
 {
 	SSI_ASSERT(cli && !inval(1,cli));
-	if (set)
+	if (set) {
+#ifdef RMTFB_REFCNT_FIX
+		atomic_inc(&rfb->rfb_refcnt);
+#endif
 		set_bit(cli - 1, &rfb->rfb_clients[0]);
-	else
+	} else {
 		clear_bit(cli - 1, &rfb->rfb_clients[0]);
+#ifdef RMTFB_REFCNT_FIX
+		rmtfb_putsvr(rfb);
+#endif
+	}
 }
 
 static inline int
 rmtfb_nocli(struct rmtfb_svr *rfb)
 {
+#ifndef RMTFB_REFCNT_FIX
 	int ctr = 0;
 	volatile unsigned long *word = rfb->rfb_clients;
 	for (; ctr < rfb_clients_len; ++ctr, ++word)
 		if (*word)
 			return 0;
+#endif
 	return 1;
 }
 
@@ -225,14 +234,16 @@
 	}
 
 	file = reop_make_file(path, flags, node);
-	error = PTR_ERR(file);
-	if (IS_ERR(file))
+	if (IS_ERR(file)) {
+		error = PTR_ERR(file);
 		goto out;
+	}
 
 	rfb = rmtfb_newsvr(file, id, cli);
-	error = PTR_ERR(rfb);
-	if (IS_ERR(rfb))
+	if (IS_ERR(rfb)) {
+		error = PTR_ERR(rfb);
 		goto file_out;
+	}
 	rmtfb_putsvr(rfb);
 	error = 0;
 file_out:
@@ -335,9 +346,10 @@
 	}
 
 	rfb = rmtfb_getsvr_handle(svrhandle);
-	error = PTR_ERR(rfb);
-	if (IS_ERR(rfb))
+	if (IS_ERR(rfb)) {
+		error = PTR_ERR(rfb);
 		goto out;
+	}
 	rmtfb_set_bit(cli, rfb, set);
 	rmtfb_putsvr(rfb);
 	error = 0;
@@ -441,7 +453,7 @@
 	if (rfb->rfb_server == node) {
 		rfb->common.rfb_file->f_op = &ssidev_bad_fops;
 #ifndef RMTFB_GETCLI_ID__RFB_SERVER_INVAL_FIX
-		/* prevent rclose() from talking to the server */
+		/* prevent rmtfb_rclose() from talking to the server */
 		rfb->rfb_server = CLUSTERNODE_INVAL;
 #endif
 	}
@@ -459,8 +471,10 @@
 
 	struct rmtfb_svr *rfb = (struct rmtfb_svr *)cmn;
 	rmtfb_set_bit(ap->node, rfb, 0);
+#ifndef RMTFB_REFCNT_FIX
 	if (!atomic_read(&rfb->rfb_refcnt) && rmtfb_nocli(rfb))
 		list_move(&rfb->common.rfb_hash, ap->list);
+#endif
 }
 
 typedef void rmtfb_nodedown_do(struct rmtfb_cmn *, u_long);
@@ -493,9 +507,11 @@
 		clusternode_t surrogate,
 		void *private)
 {
+#ifndef RMTFB_REFCNT_FIX
 	struct list_head *cur;
 	LIST_HEAD(freelist);
 	struct rmtfb_clrnode_arg rca;
+#endif
 
 	SSI_ASSERT(node && !inval(1,node));
 
@@ -505,6 +521,11 @@
 	rmtfb_nodedown_cmn(rmtfb_clitbl, rmtfb_badops, (u_long)node);
 	UNLOCK_SHR_RW_LOCK(&rmtfb_clitbl_lock);
 
+#ifdef RMTFB_REFCNT_FIX
+	LOCK_EXCL_RW_LOCK(&rmtfb_svrtbl_lock);
+	rmtfb_nodedown_cmn(rmtfb_svrtbl, rmtfb_clrnode, 0);
+	UNLOCK_EXCL_RW_LOCK(&rmtfb_svrtbl_lock);
+#else
 	rca.node = node;
 	rca.list = &freelist;
 	LOCK_EXCL_RW_LOCK(&rmtfb_svrtbl_lock);
@@ -516,6 +537,7 @@
 			list_entry(cur, struct rmtfb_cmn, rfb_hash);
 		rmtfb_freesvr(rfb);
 	}
+#endif
 
 	clms_nodedown_callback(clms_handle, service, node);
 	return 0;
@@ -652,12 +674,17 @@
 	rmtfb_svr_debug("rmtfb_putsvr",rfb);
 #endif /* RFBDEBUG */
 
+#ifndef RMTFB_REFCNT_FIX
+	/* SSI_XXX: does rfb_refcnt go negative when !rmtfb_nocli() ? */
 	SSI_ASSERT(atomic_read(&rfb->rfb_refcnt));
+#endif
 	LOCK_SHR_RW_LOCK(&rmtfb_svrtbl_lock);
 	if (atomic_dec_and_test(&rfb->rfb_refcnt) && rmtfb_nocli(rfb)) {
 		atomic_inc(&rfb->rfb_refcnt);
 		UNLOCK_SHR_RW_LOCK(&rmtfb_svrtbl_lock);
+#ifndef RMTFB_REFCNT_FIX
 		SSI_ASSERT(atomic_read(&rfb->rfb_refcnt));
+#endif
 		LOCK_EXCL_RW_LOCK(&rmtfb_svrtbl_lock);
 		if (atomic_dec_and_test(&rfb->rfb_refcnt) && rmtfb_nocli(rfb)) {
 			list_del(&rfb->common.rfb_hash);
@@ -684,7 +711,9 @@
 rmtfb_getcli_id_lckd(unsigned long id)
 {
 	struct rmtfb_cli *rfb;
+
 	SSI_ASSERT_LOCKED_SHR_RW_LOCK(&rmtfb_clitbl_lock);
+
 	rfb = (struct rmtfb_cli *) rmtfb_getcmn(
 					&rmtfb_clitbl[hash(id)],
 					rmtfb_test_id,
@@ -694,6 +723,7 @@
 		rfb = ERR_PTR(-ERFB_RELEASE);
 	else
 		SSI_ASSERT(!rfb || atomic_read(&rfb->common.rfb_file->f_count));
+
 	return rfb;
 }
 
@@ -757,9 +787,10 @@
 		goto out;
 
 	file = reop_make_file(path, flags, svr);
-	rfb = (struct rmtfb_cli *)file;
-	if (IS_ERR(rfb))
+	if (IS_ERR(file)) {
+		rfb = (struct rmtfb_cli *)file;
 		goto out;
+	}
 
 	/* make socket back pointer */
 	if (file->f_dentry->d_inode->i_sock) {
@@ -880,7 +911,6 @@
 	error = reop_export_path(file->f_dentry, file->f_vfsmnt, 0, svr, &pdp);
 	if (error >= 0) {
 		save_nc = current->node_context;
-		mb();
 		current->node_context = svr;
 		error = reop_import_path(pdp, &dp, &mp);
 		current->node_context = save_nc;

Index: ssidev.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/util/ssidev.c,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -d -r1.26 -r1.27
--- ssidev.c	24 Mar 2009 04:26:28 -0000	1.26
+++ ssidev.c	27 Oct 2009 03:18:29 -0000	1.27
@@ -70,7 +70,7 @@
 static DECLARE_MUTEX(ssidev_sem);
 #else
 static char		ssidev_busy;
-static DEFINE_SPINLOCK(ssidev_spinlock);
+static __cacheline_aligned_in_smp DEFINE_SPINLOCK(ssidev_spinlock);
 #endif
 static ssidev_hash_t	*ssidev_linux_hash[SSIDEV_HASH_SIZE];
 static ssidev_hash_t	*ssidev_ssi_hash[SSIDEV_HASH_SIZE];
@@ -83,7 +83,7 @@
 static int		ssidev_secondary_nodes;
 
 static LIST_HEAD(ssidev_poll_cli_list);
-static DEFINE_SPINLOCK(ssidev_poll_cli_spinlock);
+static __cacheline_aligned_in_smp DEFINE_SPINLOCK(ssidev_poll_cli_spinlock);
 static clusternode_t	 ssidev_mount_sem_node;
 static pid_t		 ssidev_mount_sem_epid;
 static DECLARE_MUTEX(ssidev_mount_sem);
@@ -112,7 +112,8 @@
 #define pc_wakeup	0x1	/* wake pc_proc */
 #endif
 
-static inline ssidev_hash_t *
+/* Called under ssidev_lock */
+static ssidev_hash_t *
 ssidev_search_linuxtossi(clusternode_t devnode, int mode, dev_t linuxdev)
 {
 	ssidev_hash_t *hp;
@@ -132,7 +133,8 @@
 	return hp;
 }
 
-static inline ssidev_hash_t *
+/* Called under ssidev_lock */
+static ssidev_hash_t *
 ssidev_search_ssitolinux(dev_t ssidev)
 {
 	ssidev_hash_t *hp;
@@ -149,23 +151,23 @@
 	return hp;
 }
 
+/* Called under ssidev_lock */
 static inline void ssidev_add(ssidev_hash_t *newp, clusternode_t devnode,
 			      int mode, dev_t linuxdev, dev_t ssidev)
 {
-	int lhash;
-	int shash;
+	int lhash, shash;
 
 	newp->sd_data.sd_devnode = devnode;
 	newp->sd_data.sd_ssidev = ssidev;
 	newp->sd_data.sd_linuxdev = linuxdev;
 	newp->sd_data.sd_mode = mode & S_IFMT;
+
 	lhash = SSIDEV_HASH_LINUXDEV(devnode, mode, linuxdev);
 	newp->sd_linuxnext = (void *)ssidev_linux_hash[lhash];
-	mb();
 	ssidev_linux_hash[lhash] = newp;
+
 	shash = SSIDEV_HASH_SSIDEV(ssidev);
 	newp->sd_ssinext = (void *)ssidev_ssi_hash[shash];
-	mb();
 	ssidev_ssi_hash[shash] = newp;
 }
 
@@ -174,6 +176,7 @@
 #define ssidev_lock_busy	ssidev_lock
 #define ssidev_lock_makebusy()	do { } while(0)
 #define ssidev_unlock()		up(&ssidev_sem)
+#define ssidev_lock_failover	ssidev_lock_busy
 #else
 static void
 ssidev_do_locksleep(void)
@@ -231,7 +234,6 @@
 	} else
 		spin_unlock(&ssidev_spinlock);
 }
-#endif /* !SSIDEV_LOCK_MUTEX */
 
 static void ssidev_lock_failover(void)
 {
@@ -239,6 +241,7 @@
 		return;
 	ssidev_lock_busy();
 }
+#endif /* !SSIDEV_LOCK_MUTEX */
 
 #ifdef SSIDEV_HASH_KMEM_CACHE
 static void ssidev_hash_init(void)
@@ -250,6 +253,7 @@
 }
 #endif
 
+/* Called under ssidev_lock */
 static ssidev_hash_t *
 ssidev_add_last(ssidev_hash_data_t *dp)
 {
@@ -289,6 +293,7 @@
 			} else {
 #ifdef SSIDEV_HASH_KMEM_CACHE
 				newp = kmem_cache_alloc(ssidev_hash_cachep, GFP_KERNEL|__GFP_NOFAIL);
+				INIT_LIST_HEAD(&newp->sd_list);
 #else
 				newp = kmalloc_nofail(sizeof(*newp));
 #endif
@@ -316,6 +321,7 @@
 	return newp;
 }
 
+/* Called under ssidev_lock */
 static void
 ssidev_sync_add_entries(int num, ssidev_hash_data_t *dp)
 {
@@ -344,6 +350,7 @@
 	}
 }
 
+/* Called under ssidev_lock */
 void
 ssidev_sync_data(int secondary, dev_t curdev, int transid,
 		 int secondary_nodes, nsc_nodelist_t *secondary_nodelistp,
@@ -415,6 +422,7 @@
 	return 0;
 }
 
+/* Called under ssidev_lock */
 static int ssidev_alloc_next(dev_t *ssidevp)
 {
 	ssidev_hash_t *hp;
@@ -469,6 +477,10 @@
 		ssidev_add(newp, devnode, mode, linuxdev, *ssidevp);
 		ssidev_broadcast_new(newp);
 	}
+#ifdef SSIDEV_HASH_KMEM_CACHE
+	else
+		kmem_cache_free(ssidev_hash_cachep, newp);
+#endif
 	ssidev_unlock();
 
 	return 0;
@@ -500,6 +512,10 @@
 		list_add(&newp->sd_list, &ssidev_unique_list);
 		ssidev_broadcast_new(newp);
 	}
+#ifdef SSIDEV_HASH_KMEM_CACHE
+	else
+		kmem_cache_free(ssidev_hash_cachep, newp);
+#endif
 	ssidev_unlock();
 
 	return 0;
@@ -623,6 +639,7 @@
 	return 0;
 }
 
+/* Called under ssidev_lock */
 static void
 ssidev_failover_update(ssidev_failover_data_t *fp)
 {
@@ -657,7 +674,9 @@
 	if (buffer_len == 0)
 		return;
 	SSI_ASSERT(buffer_len == sizeof(ssidev_failover_data_t));
+	ssidev_lock_busy(); /* SSI: lock for possible ssidev_add_last() path */
 	ssidev_failover_update((void *)buffer);
+	ssidev_unlock();
 }
 
 void ssidev_failover(nsc_nodelist_t *nodelist)
@@ -688,7 +707,6 @@
 {
 	/* Wait for the SSI device server if we're not it. */
 	ssidev_node = clms_get_key_server_node(ssidev_key_service, 1);
-	/* wmb(); */
 #ifdef SSIDEV_HASH_KMEM_CACHE
 	ssidev_hash_init();
 #endif
@@ -1171,6 +1189,9 @@
 				SSI_ASSERT(sfop != NULL);
 				*sfop = *sfdp;
 			}
+#ifdef RCU_SSIDEV_POLL_CLI_LIST
+			cond_resched();
+#endif
 		}
 	}
 
@@ -1646,7 +1667,6 @@
 		}
 #endif
 		save_nc = current->node_context;
-		mb();
 		current->node_context = CLUSTERNODE_THIS;
 		error = reop_import_path(pdp, &dp, &mp);
 		current->node_context = save_nc;

Index: nfs_mount.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/util/nfs_mount.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- nfs_mount.c	24 Mar 2009 04:26:28 -0000	1.12
+++ nfs_mount.c	27 Oct 2009 03:18:29 -0000	1.13
@@ -85,6 +85,7 @@
 			goto undo;
 		}
 	}
+	NSC_NODELIST_FREE(nl);
 	free_page(page);
 	return 0;
 
@@ -137,6 +138,7 @@
 		if (rval)
 			BUG();
 	}
+	NSC_NODELIST_FREE(nl);
 	ssi_put_mntid(mnt);
 
 	return finalerror;
@@ -262,6 +264,7 @@
 		if (rval)
 			BUG();
 	}
+	NSC_NODELIST_FREE(nl);
 	/* SSI_XXX: This leaves a window in which the ssidev has been
 	 * returned but local umount hasn't been started yet.  Maybe
 	 * global mount lock handles that case.
@@ -295,6 +298,7 @@
 		if (rval)
 			BUG();
 	}
+	NSC_NODELIST_FREE(nl);
 	return error;
 }
 

Index: ssipty.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/util/ssipty.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- ssipty.c	24 Mar 2009 04:26:28 -0000	1.14
+++ ssipty.c	27 Oct 2009 03:18:29 -0000	1.15
@@ -62,7 +62,7 @@
 static struct list_head *ssipty_svr_table;
 static long *ssipty_cli_bitmap;
 static long *ssipty_svr_bitmap;
-static DEFINE_RWLOCK(ssipty_rwlock); 
+static __cacheline_aligned_in_smp DEFINE_RWLOCK(ssipty_rwlock);
 static DECLARE_RWSEM(ssipty_failover_rwsem);
 
 /*
@@ -110,6 +110,7 @@
  * Utils
  */
 
+/* Called while holding write_lock on ssipty_rwlock */
 static void
 ssiptysvr_add_entry(struct ssipty_svr_entry *sep)
 {
@@ -119,6 +120,7 @@
 	__set_bit(sep->sp_entry.sp_ptynum, ssipty_svr_bitmap);
 }
 
+/* Called while holding write_lock on ssipty_rwlock */
 static void
 ssiptysvr_del_entry(struct ssipty_svr_entry *sep)
 {
@@ -127,51 +129,37 @@
 	kfree(sep);
 }
 
+/* Called while holding ssipty_rwlock */
 static struct ssipty_svr_entry *
 ssiptysvr_find_pty(int ptynum, int write_locked)
 {
-	struct ssipty_svr_entry *sep = NULL;
-	struct list_head *cur;
+	struct ssipty_svr_entry *sep;
 
-	if (ptynum < 0 || ptynum >= SSIPTY_PTYS) {
-		if (write_locked)
-			write_unlock(&ssipty_rwlock);
-		else
-			read_unlock(&ssipty_rwlock);
+	if (unlikely(ptynum < 0 || ptynum >= SSIPTY_PTYS)) {
 		printk(KERN_WARNING
 		       "%s:ptynum %d invalid\n",
 		       __FUNCTION__, ptynum);
-		if (write_locked)
-			write_lock(&ssipty_rwlock);
-		else
-			read_lock(&ssipty_rwlock);
 		return NULL;
 	}
+	list_for_each_entry(sep,
+			&ssipty_svr_table[ptynum & (SSIPTY_HASH_SIZE - 1)],
+			sp_list) {
+		if (sep->sp_entry.sp_ptynum == ptynum)
+			goto found;
+	}
+	return NULL;
+
+found:
 	if (!test_bit(ptynum, ssipty_svr_bitmap)) {
-		if (write_locked)
-			write_unlock(&ssipty_rwlock);
-		else
-			read_unlock(&ssipty_rwlock);
-#if 0
 		printk(KERN_WARNING
 		       "%s:ptynum %d not set in bitmap\n",
 		       __FUNCTION__, ptynum);
-#endif
-		if (write_locked)
-			write_lock(&ssipty_rwlock);
-		else
-			read_lock(&ssipty_rwlock);
-
-	}
-	list_for_each(cur, &ssipty_svr_table[ptynum & (SSIPTY_HASH_SIZE - 1)]) {
-		sep = list_entry(cur, struct ssipty_svr_entry, sp_list);
-		if (sep->sp_entry.sp_ptynum == ptynum)
-			break;
 	}
 
 	return sep;
 }
 
+/* Called while holding write_lock on ssipty_rwlock */
 static void
 ssiptysvr_put_pty(clusternode_t from_node, int ptynum)
 {
@@ -233,10 +221,9 @@
 static void
 ssipty_failover_data(clusternode_t node, char *buffer, int data_len)
 {
-	struct ssipty_entry *ep;
+	struct ssipty_entry *ep = (struct ssipty_entry *)buffer;
 	int ctr;
 
-	ep = (struct ssipty_entry *)buffer;
 	for (ctr = 0; ctr < data_len / sizeof(*ep); ++ep, ++ctr) {
 		struct ssipty_svr_entry *sep;
 
@@ -256,8 +243,12 @@
 		sep = kmalloc_nofail(sizeof(*sep));
 		sep->sp_entry = *ep;
 		sep->sp_ptysvr = node;
+
 		write_lock(&ssipty_rwlock);
-		ssiptysvr_add_entry(sep);
+		if (test_bit(ep->sp_ptynum, ssipty_svr_bitmap)) {
+			kfree(sep); /* Lost the race */
+		} else
+			ssiptysvr_add_entry(sep);
 		write_unlock(&ssipty_rwlock);
 	}
 }
@@ -274,8 +265,10 @@
 	bufent = buffer_len / sizeof(*ep);
 	*data_len = 0;
 	ptynum = -1;
+
 	if (this_node != ssipty_node)
 		down_write(&ssipty_failover_rwsem);
+
 	read_lock(&ssipty_rwlock);
 	for (;;) {
 		ptynum = find_next_bit(ssipty_cli_bitmap, SSIPTY_PTYS,
@@ -305,15 +298,13 @@
 ssiptysvr_nodedown(clusternode_t node)
 {
 	int hash;
-	struct ssipty_svr_entry *sep;
+	struct ssipty_svr_entry *sep, *next;
 
 	down_read(&ssipty_failover_rwsem);
+
 	write_lock(&ssipty_rwlock);
 	for (hash = 0; hash < SSIPTY_HASH_SIZE; ++hash) {
-		struct list_head *cur, *next;
-		list_for_each_safe(cur, next, &ssipty_svr_table[hash]) {
-
-			sep = list_entry(cur, struct ssipty_svr_entry, sp_list);
+		list_for_each_entry_safe(sep, next, &ssipty_svr_table[hash], sp_list) {
 			if (sep->sp_ptysvr == node)
 				ssiptysvr_del_entry(sep);
 		}
@@ -348,26 +339,31 @@
 	*rerror = 0;
 	if (ptymax > SSIPTY_PTYS)
 		ptymax = SSIPTY_PTYS;
+
 	sep = kmalloc(sizeof(*sep), GFP_KERNEL);
 	if (sep == NULL) {
 		*rerror = -ENOMEM;
-		goto out;
+		return 0;
 	}
+
 	write_lock(&ssipty_rwlock);
+
 	if (*ptynum != -1)
 		ssiptysvr_put_pty(from_node, *ptynum);
+
 	*ptynum = find_next_zero_bit(ssipty_svr_bitmap, ptymax, *ptynum + 1);
-	if (*ptynum >= ptymax) {
+	if (unlikely(*ptynum >= ptymax)) {
+		write_unlock(&ssipty_rwlock);
 		*rerror = -EIO;
 		kfree(sep);
-		goto out;
+		return 0;
 	}
+
 	INIT_LIST_HEAD(&sep->sp_list);
 	sep->sp_ptysvr = from_node;
 	sep->sp_entry.sp_ptynum = *ptynum;
 	ssiptysvr_add_entry(sep);
 	write_unlock(&ssipty_rwlock);
- out:
 	return 0;
 }
 
@@ -387,25 +383,25 @@
 rssipty_readdir(clusternode_t node, int *rerror, int idx,
 		struct ssipty_entry **entries, int *entries_len)
 {
-	int ptynum;
 	struct ssipty_entry *ep;
-	int cnt;
+	int ptynum = -1;
+	int cnt = *entries_len;
 
 	*rerror = 0;
 
-	cnt = *entries_len;
-	*entries_len = 0;
 	if (*entries == NULL) {
 		if (cnt != 0)
 			*entries = kmalloc(sizeof(**entries) * cnt, GFP_KERNEL);
 		if (*entries == NULL) {
 			*rerror = -ENOMEM;
-			goto out;
+			return 0;
 		}
 	}
-	ptynum = -1;
 	ep = *entries;
+	*entries_len = 0;
+
 	read_lock(&ssipty_rwlock);
+
 	while (*entries_len < cnt) {
 		ptynum = find_next_bit(ssipty_svr_bitmap, SSIPTY_PTYS,
 				       ptynum + 1);
@@ -419,7 +415,6 @@
 			idx--;
 	}
 	read_unlock(&ssipty_rwlock);
- out:
 	return 0;
 }
 
@@ -432,12 +427,13 @@
 	*rerror = 0;
 
 	read_lock(&ssipty_rwlock);
+
 	sep = ssiptysvr_find_pty(ptynum, 0);
-	read_unlock(&ssipty_rwlock);
 	if (sep != NULL)
 		*ptysvr = sep->sp_ptysvr;
 	else
 		*rerror = -ENOENT;
+	read_unlock(&ssipty_rwlock);
 
 	return 0;
 }
@@ -447,7 +443,6 @@
 		  struct iattr *iattr)
 {
 	*rerror = ssipty_get_iattr(ptynum, iattr);
-
 	return 0;
 }
 
@@ -456,7 +451,6 @@
 		  struct iattr *iattr)
 {
 	*rerror = ssipty_set_iattr(ptynum, iattr);
-
 	return 0;
 }
 
@@ -543,8 +537,10 @@
 rpc_repeat:
 	server = ssipty_node;
 	down_read(&ssipty_failover_rwsem);
+
 	if (*ptynum != -1)
 		ssiptycli_clr_pty(*ptynum);
+
 	if (this_node == server)
 		ret = rssipty_get_pty(server, &error, this_node,
 				      ptymax, ptynum);
@@ -552,8 +548,10 @@
 		ret = RSSIPTY_GET_PTY(server, &error, this_node,
 				      ptymax, ptynum);
 	ssipty_rpcerror(RPC_NOINTR, 1);
+
 	if (error >= 0)
 		ssiptycli_set_pty(*ptynum);
+
 	up_read(&ssipty_failover_rwsem);
  rpc_out:
 	return error;
@@ -569,7 +567,9 @@
 rpc_repeat:
 	server = ssipty_node;
 	down_read(&ssipty_failover_rwsem);
+
 	ssiptycli_clr_pty(ptynum);
+
 	if (this_node == server)
 		ret = rssipty_put_pty(server, &error, this_node, ptynum);
 	else
@@ -590,6 +590,7 @@
 rpc_repeat:
 	server = ssipty_node;
 	down_read(&ssipty_failover_rwsem);
+
 	if (this_node == server)
 		ret = rssipty_readdir(server, &error, idx,
 				      &entries, entries_len);
@@ -638,6 +639,7 @@
 rpc_repeat:
 	server = ssipty_node;
 	down_read(&ssipty_failover_rwsem);
+
 	if (this_node == server)
 		ret = rssipty_get_server(server, &error, ptynum, ptysvr);
 	else
@@ -651,12 +653,10 @@
 int
 ssipty_update_inode(struct inode **ipp, int ptynum)
 {
-	int inode_allocated;
 	struct inode *inode;
-	int ret;
-	int error;
-	clusternode_t ptysvr;
 	struct iattr iattr;
+	clusternode_t ptysvr;
+	int ret, error;
 
 	error = ssipty_get_server(ptynum, &ptysvr);
 	if (error < 0)
@@ -664,15 +664,16 @@
 	if (ptysvr == this_node)
 		/* Raced */
 		return -EINVAL;
-	inode_allocated = (!*ipp);
-	if (inode_allocated) {
-		inode = *ipp = ssipty_init_inode(*ipp, ptynum, ptysvr);
-		if (!*ipp)
+
+	if (!(inode = *ipp)) {
+		/* allocate inode */
+		inode = ssipty_init_inode(inode, ptynum, ptysvr);
+		if (!inode)
 			return -ENOMEM;
-	} else
-		inode = *ipp;
+	}
 rpc_repeat:
 	down_read(&ssipty_failover_rwsem);
+
 	ret = RSSIPTY_GET_IATTR(ptysvr, &error, ptynum, &iattr);
 	up_read(&ssipty_failover_rwsem);
 	if (ret)
@@ -693,10 +694,10 @@
 		inode->i_mtime = iattr.ia_mtime;
 		inode->i_ctime = iattr.ia_ctime;
 		inode->i_mode = iattr.ia_mode;
-	} else if (inode_allocated) {
-		iput(inode);
-		*ipp = NULL;
-	}
+		if (!*ipp)
+			*ipp = inode;
+	} else if (!*ipp)
+		iput(inode); /* free allocated */
 
 	return error;
 }
@@ -880,6 +881,7 @@
 			BUG();
 		}
 	}
+	NSC_NODELIST_FREE(nl);
 	free_page(page);
 	return 0;
 }
@@ -1049,6 +1051,7 @@
 		if (rval)
 			BUG();
 	}
+	NSC_NODELIST_FREE(nl);
 	ssi_put_mntid(mnt);
 	return 0;
 
@@ -1077,6 +1080,7 @@
 		if (rval)
 			BUG();
 	}
+	NSC_NODELIST_FREE(nl);
 	return error;
 }
 

Index: gfs_mount.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/util/gfs_mount.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- gfs_mount.c	24 Mar 2009 04:26:28 -0000	1.8
+++ gfs_mount.c	27 Oct 2009 03:18:29 -0000	1.9
@@ -63,6 +63,7 @@
 			BUG();
 		}
 	}
+	NSC_NODELIST_FREE(nl);
 	free_page(page);
 	return 0;
 }
@@ -178,6 +179,7 @@
 		if (rval)
 			BUG();
 	}
+	NSC_NODELIST_FREE(nl);
 	return 0;
 
 abort:
@@ -204,6 +206,7 @@
 		if (rval)
 			BUG();
 	}
+	NSC_NODELIST_FREE(nl);
 	return error;
 }
 

Index: ssidev_ics.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/util/ssidev_ics.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- ssidev_ics.c	24 Mar 2009 04:26:28 -0000	1.14
+++ ssidev_ics.c	27 Oct 2009 03:18:29 -0000	1.15
@@ -51,7 +51,7 @@
 #include <cluster/gen/icssvr_ssidev_tables_gen.c>
 
 static LIST_HEAD(ssidev_poll_svr_list);
-static DEFINE_SPINLOCK(ssidev_poll_svr_spinlock); 
+static __cacheline_aligned_in_smp DEFINE_SPINLOCK(ssidev_poll_svr_spinlock);
 #ifdef SSIDEV_POLL_SVR_KMEM_CACHE
 static kmem_cache_t *ssidev_poll_svr_cachep;
 #endif
@@ -238,7 +238,9 @@
 {
 	struct rmtfb_svr *rfb = rmtfb_getsvr_handle(svrhandle);
 	struct file *file;
+#ifndef SSI_RW_VERIFY_AREA_FIX
 	ssize_t (*fn)(struct file *, char *, size_t, loff_t *);
+#endif
 	ssi_procstate_t save_pstate;
 	char *buf;
 	int count;
@@ -251,10 +253,15 @@
 	if (!IS_ERR(rfb)) {
 		*retval = -EINVAL;
 		file = rfb->common.rfb_file;
-		if (file->f_op && (fn = file->f_op->read))
 #ifdef SSI_RW_VERIFY_AREA_FIX
-			*retval = fn(file, buf, count, ppos);
+		if (file->f_op) {
+			if (file->f_op->read)
+				*retval = file->f_op->read(file, buf, count, ppos);
+			else
+				*retval = do_sync_read(file, buf, count, ppos);
+		}
 #else
+		if (file->f_op && (fn = file->f_op->read))
 			*retval = fn(file, buf, count, &file->f_pos);
 #endif
 		rmtfb_putsvr(rfb);
@@ -314,7 +321,9 @@
 {
 	struct rmtfb_svr *rfb = rmtfb_getsvr_handle(svrhandle);
 	struct file *file;
+#ifndef SSI_RW_VERIFY_AREA_FIX
 	ssize_t (*fn)(struct file *, const char *, size_t, loff_t *);
+#endif
 	ssi_procstate_t save_pstate;
 	char *buf;
 	int count;
@@ -327,10 +336,15 @@
 	if (!IS_ERR(rfb)) {
 		*retval = -EINVAL;
 		file = rfb->common.rfb_file;
-		if (file->f_op && (fn = file->f_op->write))
 #ifdef SSI_RW_VERIFY_AREA_FIX
-			*retval = fn(file, buf, count, ppos);
+		if (file->f_op) {
+			if (file->f_op->write)
+				*retval = file->f_op->write(file, buf, count, ppos);
+			else
+				*retval = do_sync_write(file, buf, count, ppos);
+		}
 #else
+		if (file->f_op && (fn = file->f_op->write))
 			*retval = fn(file, buf, count, &file->f_pos);
 #endif
 		rmtfb_putsvr(rfb);


------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay 
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
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.