[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