[SSI] openssi/kernel/cluster/ssi/ipc rmtunix.c,1.22,1.23
Roger Tsang <[email protected]>
| Newsgroups | gmane.linux.cluster.ssic.cvs |
|---|---|
| Message-ID | <[email protected]> |
Update of /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/ipc
In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvs-serv8553/cluster/ssi/ipc
Modified Files:
Tag: OPENSSI-FC
rmtunix.c
Log Message:
Bug fixes and enhancements. (see ChangeLog)
Index: rmtunix.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/ipc/rmtunix.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- rmtunix.c 10 Oct 2008 08:10:32 -0000 1.22
+++ rmtunix.c 3 Feb 2009 06:18:12 -0000 1.23
@@ -45,11 +45,12 @@
#include <cluster/gen/ics_unixnm_macros_gen.h>
#include <cluster/gen/ics_unixnm_protos_gen.h>
-struct scm_cookie;
+//struct scm_cookie;
-struct list_head rmtunix_cache_list =
- LIST_HEAD_INIT(rmtunix_cache_list);
+LIST_HEAD(rmtunix_cache_list);
+#ifdef DEBUG
int rmtunix_cache_size = 0;
+#endif
DEFINE_SPINLOCK(rmtunix_cache_listlock);
extern int sysctl_unix_max_dgram_qlen;
@@ -61,21 +62,108 @@
void unix_write_space(struct sock *sk);
+#ifdef RMTUNIX_SOCK_INFO_CACHE
+kmem_cache_t *rmtunix_socket_info_cachep;
+
+static int __init rmtunix_init(void)
+{
+ rmtunix_socket_info_cachep = kmem_cache_create("rmtunix_socket_info",
+ sizeof(struct rmtunix_socket_info), 0,
+ SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|SLAB_PANIC,
+ NULL, NULL);
+ return 0;
+}
+
+/* XXX: There is currently no option to compile this as a module. */
+module_init(rmtunix_init);
+#endif
+
+static inline void
+_rmtunix_dealloc(struct rmtunix_socket_info *info)
+{
+#ifdef IPC_STALE_RMTUNIX_CACHE_FIX
+ if (info->sk) {
+#endif
+ unix_peer(info->sk) = NULL;
+ if (!rmtunix_ismagic(info->sk))
+ sock_put(info->sk);
+ info->sk = NULL;
+#ifdef IPC_STALE_RMTUNIX_CACHE_FIX
+ }
+#endif
+ info->magic = 0;
+#ifdef RMTUNIX_SOCK_INFO_CACHE
+ kmem_cache_free(rmtunix_socket_info_cachep, info);
+#else
+ kfree(info);
+#endif
+}
+
+#ifdef RCU_RMTUNIX_CACHE
+void
+rmtunix_dealloc(struct rcu_head *rhead)
+{
+ _rmtunix_dealloc(container_of(rhead, struct rmtunix_socket_info, rhead));
+}
+#endif
void
rmtunix_nodedown(clusternode_t node)
{
struct list_head *cur, *next;
- struct list_head list = LIST_HEAD_INIT(list);
+#ifdef RCU_RMTUNIX_CACHE
+ might_sleep();
+
+ rcu_read_lock();
+ list_for_each_safe_rcu(cur, next, &rmtunix_cache_list) {
+ struct rmtunix_socket_info *info = list_entry(cur,
+ struct rmtunix_socket_info, list);
+ if (info->node != node)
+ continue;
+ if (!atomic_dec_and_lock(&info->rsk_refcnt, &rmtunix_cache_listlock))
+ continue;
+#ifdef IPC_STALE_RMTUNIX_CACHE_FIX
+ if (info->sk) {
+ struct sock *s = info->sk;
+ spin_lock(&s->sk_lock.slock);
+ if (!info->rsk_cached) {
+ spin_unlock(&s->sk_lock.slock);
+ spin_unlock(&rmtunix_cache_listlock);
+ continue;
+ }
+ info->rsk_cached = 0;
+ spin_unlock(&s->sk_lock.slock);
+ } else
+ BUG_ON(info->rsk_cached);
+#endif
+#ifdef DEBUG
+ --rmtunix_cache_size;
+#endif
+ list_del_rcu(&info->list);
+ spin_unlock(&rmtunix_cache_listlock);
+ call_rcu(&info->rhead, rmtunix_dealloc);
+ }
+ rcu_read_unlock();
+#else /* !RCU_RMTUNIX_CACHE */
+ LIST_HEAD(list);
spin_lock(&rmtunix_cache_listlock);
list_for_each_safe(cur, next, &rmtunix_cache_list) {
struct rmtunix_socket_info *info = list_entry(cur,
struct rmtunix_socket_info, list);
if (info->node != node)
+#ifdef IPC_STALE_RMTUNIX_CACHE_FIX
+ continue;
+ if (!atomic_dec_and_test(&info->rsk_refcnt))
+ continue;
+ info->cached = 0;
+#else
break;
+#endif
+#ifdef DEBUG
--rmtunix_cache_size;
+#endif
list_move(&info->list, &list);
}
spin_unlock(&rmtunix_cache_listlock);
@@ -84,13 +172,9 @@
struct rmtunix_socket_info *info = list_entry(cur,
struct rmtunix_socket_info, list);
- unix_peer(info->sk) = NULL;
- sock_put(info->sk);
- info->sk = NULL;
- info->magic = 0;
- kfree(info);
+ _rmtunix_dealloc(info);
}
-
+#endif /* !RCU_RMTUNIX_CACHE */
}
static struct sock *
@@ -104,7 +188,11 @@
if (!id)
goto out;
+#ifdef RCU_RMTUNIX_CACHE
+ rcu_read_lock();
+#else
spin_lock(&rmtunix_cache_listlock);
+#endif
list_for_each(cur, &rmtunix_cache_list) {
struct rmtunix_socket_info *info = list_entry(cur,
struct rmtunix_socket_info, list);
@@ -113,7 +201,11 @@
break;
}
}
+#ifdef RCU_RMTUNIX_CACHE
+ rcu_read_unlock();
+#else
spin_unlock(&rmtunix_cache_listlock);
+#endif
if (!sk)
goto out;
@@ -485,6 +577,9 @@
char *buf = msg->msg_iov->iov_base;
size_t buflen = msg->msg_iov->iov_len;
int flags = msg->msg_flags;
+#ifdef RMTUNIX__SENDMSG_IOVECS
+ size_t iovlen = msg->msg_iovlen;
+#endif
struct rmtscm_cookie *rscm = (struct rmtscm_cookie *)siocbp->scm;
int error;
ics_userbuf_t ubuf;
@@ -492,6 +587,7 @@
SSI_ASSERT(tonode != this_node); /* SSI_OBJ: socket migrated here */
+#ifndef RMTUNIX__SENDMSG_IOVECS
if (msg->msg_iovlen > 1) {
error = -EMSGSIZE;
printk(KERN_ERR "%s: %s: current limit of one data block "
@@ -499,12 +595,46 @@
current->comm, __FUNCTION__);
goto out;
}
+#else
+ if (iovlen > 1) {
+ int i;
+ struct iovec *vec = msg->msg_iov;
+
+#ifdef SSI_SKIP
+ if ((int)total_len < 0) {
+ error = -EMSGSIZE;
+ printk(KERN_ERR "%s: %s: exceeded ics_userbuf "
+ "capacity\n",
+ current->comm, __FUNCTION__);
+ goto out;
+ }
+#endif
+
+ if (!(buf = kmalloc(total_len, GFP_KERNEL))) {
+ error = -ENOMEM;
+ goto out;
+ }
+
+ buflen = 0;
+ for (i = 0; i < msg->msg_iovlen; i++) {
+ copy_from_user(buf, vec->iov_base, vec->iov_len);
+ buflen += vec->iov_len;
+ buf += vec->iov_len;
+ vec++;
+ }
+ }
+#endif /* RMTUNIX__SENDMSG_IOVECS */
+
/* SSI_XXX: rmtsock_sendmsg() sends total_len, rather than asserting */
SSI_ASSERT(buflen == total_len);
if (!access_ok(VERIFY_READ, buf, buflen)) {
error = -EFAULT;
+#ifdef RMTUNIX__SENDMSG_IOVECS
+ goto free_out;
+#else
goto out;
+#endif
}
if (u->addr) {
@@ -542,6 +672,11 @@
break;
}
+#ifdef RMTUNIX__SENDMSG_IOVECS
+free_out:
+ if (iovlen > 1)
+ kfree(buf);
+#endif
out:
return error;
}
@@ -604,8 +739,10 @@
/* Not sure why we call sock_hold(sk) when we already have sk.
* - Vladimir Razgulin
*/
- /* This hold is for extra sock_put in label out. -Roger */
- sock_hold(sk);
+ /* RT: for _rmtunix_dealloc() */
+ if (!rmtunix_ismagic(sk))
+ sock_hold(sk);
+
unix_peer(sk) = (struct sock *)info;
rmtunix_cache_info(sk);
@@ -792,6 +929,7 @@
goto out;
rmtunix_decache_info(sk);
+#ifdef SSIC_LINUX_BUG_1764324
/* ssic-linux-bug [ 1764324 ]:
* Badness in sk_del_node_init at include/net/sock.h:343
*/
@@ -799,7 +937,6 @@
* unix_remove_socket(). -Vladimir Razgulin
*/
/* No hold for remote socket; see ssi_unix_sock_hold(). -Roger */
-#ifdef SSIC_LINUX_BUG_1764324
/* Peer */
sock_put(sk);
#endif
@@ -1062,7 +1199,7 @@
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;
vec++;
------------------------------------------------------------------------------
Create and Deploy Rich Internet Apps outside the browser with Adobe(R)AIR(TM)
software. With Adobe AIR, Ajax developers can use existing skills and code to
build responsive, highly engaging applications that combine the power of local
resources and data with the reach of the web. Download the Adobe AIR SDK and
Ajax docs to start building applications today-http://p.sf.net/sfu/adobe-com