[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
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.