All of lore.kernel.org
 help / color / mirror / Atom feed
diff for duplicates of <20111222155212.GA21486@ca-server1.us.oracle.com>

diff --git a/a/1.txt b/N1/1.txt
index 8b13789..cb24c64 100644
--- a/a/1.txt
+++ b/N1/1.txt
@@ -1 +1,600 @@
+>From 3a84584164119d3c08b2857fe45313cbd4df9a00 Mon Sep 17 00:00:00 2001
+From: Dan Magenheimer <dan.magenheimer@oracle.com>
+Date: Wed, 21 Dec 2011 14:02:01 -0700
+Subject: [PATCH V2 5/6] drivers/staging/ramster: ramster-specific new files
 
+New files for ramster support:  The file ramster.h declares externs
+and some pampd bitfield manipulation.  The file zcache.h declares
+some zcache functions that now must be accessed from the ramster
+glue code.  The file ramster_o2net.c is the glue between
+zcache and the o2net messaging code, providing routines called
+from zcache that initiate messages, and routines that handle
+messages by calling zcache.
+
+Signed-off-by: Dan Magenheimer <dan.magenheimer@oracle.com>
+
+---
+
+ drivers/staging/ramster/ramster.h       |  117 +++++++++
+ drivers/staging/ramster/ramster_o2net.c |  419 +++++++++++++++++++++++++++++++
+ drivers/staging/ramster/zcache.h        |   22 ++
+ 3 files changed, 558 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/staging/ramster/ramster.h b/drivers/staging/ramster/ramster.h
+new file mode 100644
+index 0000000..3293512
+--- /dev/null
++++ b/drivers/staging/ramster/ramster.h
+@@ -0,0 +1,117 @@
++/*
++ * ramster.h
++ *
++ * Peer-to-peer transcendent memory
++ *
++ * Copyright (c) 2009-2012, Dan Magenheimer, Oracle Corp.
++ */
++
++#ifndef _RAMSTER_H_
++#define _RAMSTER_H_
++
++/*
++ * format of remote pampd:
++ *   bit 0 == intransit
++ *   bit 1 == is_remote... if this bit is set, then
++ *   bit 2-9 == remotenode
++ *   bit 10-22 == size
++ *   bit 23-30 == cksum
++ */
++#define FAKE_PAMPD_INTRANSIT_BITS	1
++#define FAKE_PAMPD_ISREMOTE_BITS	1
++#define FAKE_PAMPD_REMOTENODE_BITS	8
++#define FAKE_PAMPD_REMOTESIZE_BITS	13
++#define FAKE_PAMPD_CHECKSUM_BITS	8
++
++#define FAKE_PAMPD_INTRANSIT_SHIFT	0
++#define FAKE_PAMPD_ISREMOTE_SHIFT	(FAKE_PAMPD_INTRANSIT_SHIFT + \
++					 FAKE_PAMPD_INTRANSIT_BITS)
++#define FAKE_PAMPD_REMOTENODE_SHIFT	(FAKE_PAMPD_ISREMOTE_SHIFT + \
++					 FAKE_PAMPD_ISREMOTE_BITS)
++#define FAKE_PAMPD_REMOTESIZE_SHIFT	(FAKE_PAMPD_REMOTENODE_SHIFT + \
++					 FAKE_PAMPD_REMOTENODE_BITS)
++#define FAKE_PAMPD_CHECKSUM_SHIFT	(FAKE_PAMPD_REMOTESIZE_SHIFT + \
++					 FAKE_PAMPD_REMOTESIZE_BITS)
++
++#define FAKE_PAMPD_MASK(x)		((1UL << (x)) - 1)
++
++static inline void *pampd_make_remote(int remotenode, size_t size,
++					unsigned char cksum)
++{
++	unsigned long fake_pampd = 0;
++	fake_pampd |= 1UL << FAKE_PAMPD_ISREMOTE_SHIFT;
++	fake_pampd |= ((unsigned long)remotenode &
++			FAKE_PAMPD_MASK(FAKE_PAMPD_REMOTENODE_BITS)) <<
++				FAKE_PAMPD_REMOTENODE_SHIFT;
++	fake_pampd |= ((unsigned long)size &
++			FAKE_PAMPD_MASK(FAKE_PAMPD_REMOTESIZE_BITS)) <<
++				FAKE_PAMPD_REMOTESIZE_SHIFT;
++	fake_pampd |= ((unsigned long)cksum &
++			FAKE_PAMPD_MASK(FAKE_PAMPD_CHECKSUM_BITS)) <<
++				FAKE_PAMPD_CHECKSUM_SHIFT;
++	return (void *)fake_pampd;
++}
++
++static inline unsigned int pampd_remote_node(void *pampd)
++{
++	unsigned long fake_pampd = (unsigned long)pampd;
++	return (fake_pampd >> FAKE_PAMPD_REMOTENODE_SHIFT) &
++		FAKE_PAMPD_MASK(FAKE_PAMPD_REMOTENODE_BITS);
++}
++
++static inline unsigned int pampd_remote_size(void *pampd)
++{
++	unsigned long fake_pampd = (unsigned long)pampd;
++	return (fake_pampd >> FAKE_PAMPD_REMOTESIZE_SHIFT) &
++		FAKE_PAMPD_MASK(FAKE_PAMPD_REMOTESIZE_BITS);
++}
++
++static inline unsigned char pampd_remote_cksum(void *pampd)
++{
++	unsigned long fake_pampd = (unsigned long)pampd;
++	return (fake_pampd >> FAKE_PAMPD_CHECKSUM_SHIFT) &
++		FAKE_PAMPD_MASK(FAKE_PAMPD_CHECKSUM_BITS);
++}
++
++static inline bool pampd_is_remote(void *pampd)
++{
++	unsigned long fake_pampd = (unsigned long)pampd;
++	return (fake_pampd >> FAKE_PAMPD_ISREMOTE_SHIFT) &
++		FAKE_PAMPD_MASK(FAKE_PAMPD_ISREMOTE_BITS);
++}
++
++static inline bool pampd_is_intransit(void *pampd)
++{
++	unsigned long fake_pampd = (unsigned long)pampd;
++	return (fake_pampd >> FAKE_PAMPD_INTRANSIT_SHIFT) &
++		FAKE_PAMPD_MASK(FAKE_PAMPD_INTRANSIT_BITS);
++}
++
++/* note that it is a BUG for intransit to be set without isremote also set */
++static inline void *pampd_mark_intransit(void *pampd)
++{
++	unsigned long fake_pampd = (unsigned long)pampd;
++
++	fake_pampd |= 1UL << FAKE_PAMPD_ISREMOTE_SHIFT;
++	fake_pampd |= 1UL << FAKE_PAMPD_INTRANSIT_SHIFT;
++	return (void *)fake_pampd;
++}
++
++static inline void *pampd_mask_intransit_and_remote(void *marked_pampd)
++{
++	unsigned long pampd = (unsigned long)marked_pampd;
++
++	pampd &= ~(1UL << FAKE_PAMPD_INTRANSIT_SHIFT);
++	pampd &= ~(1UL << FAKE_PAMPD_ISREMOTE_SHIFT);
++	return (void *)pampd;
++}
++
++extern int ramster_remote_async_get(struct tmem_xhandle *,
++				bool, int, size_t, uint8_t, void *extra);
++extern int ramster_remote_put(struct tmem_xhandle *, char *, size_t,
++				bool, int *);
++extern int ramster_remote_flush(struct tmem_xhandle *, int);
++extern int ramster_remote_flush_object(struct tmem_xhandle *, int);
++extern int ramster_o2net_register_handlers(void);
++
++#endif /* _TMEM_H */
+diff --git a/drivers/staging/ramster/ramster_o2net.c b/drivers/staging/ramster/ramster_o2net.c
+new file mode 100644
+index 0000000..ee6a9ed
+--- /dev/null
++++ b/drivers/staging/ramster/ramster_o2net.c
+@@ -0,0 +1,419 @@
++/*
++ * ramster_o2net.c
++ *
++ * Copyright (c) 2011, Dan Magenheimer, Oracle Corp.
++ *
++ * Ramster_o2net provides an interface between zcache and o2net.
++ *
++ * FIXME: support more than two nodes
++ */
++
++#include <linux/list.h>
++#include "cluster/tcp.h"
++#include "cluster/nodemanager.h"
++#include "tmem.h"
++#include "zcache.h"
++#include "ramster.h"
++
++#define RMSTR_KEY	0x77347734
++
++enum {
++	RMSTR_TMEM_PUT_EPH = 100,
++	RMSTR_TMEM_PUT_PERS,
++	RMSTR_TMEM_ASYNC_GET_REQUEST,
++	RMSTR_TMEM_ASYNC_GET_AND_FREE_REQUEST,
++	RMSTR_TMEM_ASYNC_GET_REPLY,
++	RMSTR_TMEM_FLUSH,
++	RMSTR_TMEM_FLOBJ,
++	RMSTR_TMEM_DESTROY_POOL,
++};
++
++#define RMSTR_O2NET_MAX_LEN \
++		(O2NET_MAX_PAYLOAD_BYTES - sizeof(struct tmem_xhandle))
++
++#include "cluster/tcp_internal.h"
++
++static struct o2nm_node *ramster_choose_node(int *nodenum,
++						struct tmem_xhandle *xh)
++{
++	struct o2nm_node *node = NULL;
++	int i;
++
++/* FIXME reproducibly pick a node based on xh that is NOT this node */
++	i = o2nm_this_node();
++	i = !i;		/* FIXME ONLY FOR TWO NODES */
++	node = o2nm_get_node_by_num(i);
++		/* WARNING: THIS DOES NOT CHECK TO ENSURE CONNECTED */
++	if (node != NULL)
++		*nodenum = i;
++	return node;
++}
++
++static void ramster_put_node(struct o2nm_node *node)
++{
++	o2nm_node_put(node);
++}
++
++/* FIXME following buffer should be per-cpu, protected by preempt_disable */
++static char ramster_async_get_buf[O2NET_MAX_PAYLOAD_BYTES];
++
++static int ramster_remote_async_get_request_handler(struct o2net_msg *msg,
++				u32 len, void *data, void **ret_data)
++{
++	char *pdata;
++	struct tmem_xhandle xh;
++	int found;
++	size_t size = RMSTR_O2NET_MAX_LEN;
++	u16 msgtype = be16_to_cpu(msg->msg_type);
++	bool get_and_free = (msgtype == RMSTR_TMEM_ASYNC_GET_AND_FREE_REQUEST);
++	unsigned long flags;
++
++	xh = *(struct tmem_xhandle *)msg->buf;
++	if (xh.xh_data_size > RMSTR_O2NET_MAX_LEN)
++		BUG();
++	pdata = ramster_async_get_buf;
++	*(struct tmem_xhandle *)pdata = xh;
++	pdata += sizeof(struct tmem_xhandle);
++	local_irq_save(flags);
++	found = zcache_get(xh.client_id, xh.pool_id, &xh.oid, xh.index,
++				pdata, &size, 1, get_and_free ? 1 : -1);
++	local_irq_restore(flags);
++	if (found < 0) {
++#if 0
++static unsigned long cnt;
++cnt++;
++if (!(cnt&(cnt-1)))
++pr_err("TESTING ArrgREQ zcache_get %s failed, assuming is this OK? cnt=%lu\n",
++	(get_and_free) ? "eph" : "pers", cnt);
++#endif
++		/* a zero size indicates the get failed */
++		size = 0;
++	}
++	if (size > RMSTR_O2NET_MAX_LEN)
++		BUG();
++#if 0
++if (size != 0) {
++/* DOH! RMSTR_O2NET_MAX_LEN==4032... means zcache_get is returning failure
++   which means maybe a race with a flush? */
++unsigned char cksum;
++int i;
++char *tmp;
++for (tmp = pdata, cksum = 0, i = 0; i < size; i++)
++	cksum += *tmp;
++if ((xh.xh_data_size != size) || (xh.xh_data_cksum != cksum))
++pr_err("TESTING ArrgREQ, HUH xh_data_size=%d, exp=%d, cksum=%d, exp=%d,"
++	"xh=(%d,0x%llx.0x%llx.0x%llx,%x), %s\n",
++	(int)xh.xh_data_size, (int)size, xh.xh_data_cksum, cksum,
++	xh.pool_id, xh.oid.oid[0], xh.oid.oid[1], xh.oid.oid[2],
++	xh.index, (get_and_free ? "eph" : "pers"));
++else {
++#if 0
++static unsigned long cnt;
++cnt++;
++if (!(cnt&(cnt-1)))
++pr_err("TESTING ArrgREQ cnt=%lu, xh_data_size=%d, exp=%d, cksum=%d, exp=%d\n",
++	cnt, (int)xh.xh_data_size, (int)size, xh.xh_data_cksum, cksum);
++#endif
++}
++}
++#endif
++	*ret_data = pdata - sizeof(struct tmem_xhandle);
++	/* now make caller (o2net_process_message) handle specially */
++	o2net_force_data_magic(msg, RMSTR_TMEM_ASYNC_GET_REPLY, RMSTR_KEY);
++	return size + sizeof(struct tmem_xhandle);
++}
++
++static int ramster_remote_async_get_reply_handler(struct o2net_msg *msg,
++				u32 len, void *data, void **ret_data)
++{
++	char *in = (char *)msg->buf;
++	int datalen = len - sizeof(struct o2net_msg);
++	int ret = -1;
++	struct tmem_xhandle *xh = (struct tmem_xhandle *)in;
++
++	in += sizeof(struct tmem_xhandle);
++	datalen -= sizeof(struct tmem_xhandle);
++	BUG_ON(datalen < 0 || datalen > PAGE_SIZE);
++	ret = zcache_localify(xh->pool_id, &xh->oid, xh->index,
++				in, datalen, xh->extra);
++#if 1
++if (ret == -EEXIST)
++pr_err("TESTING ArrgREP, aborted overwrite on racy put\n");
++#endif
++	return ret;
++}
++
++int ramster_remote_put_handler(struct o2net_msg *msg,
++				u32 len, void *data, void **ret_data)
++{
++	struct tmem_xhandle *xh;
++	char *p = (char *)msg->buf;
++	int datalen = len - sizeof(struct o2net_msg) -
++				sizeof(struct tmem_xhandle);
++	u16 msgtype = be16_to_cpu(msg->msg_type);
++	bool ephemeral = (msgtype == RMSTR_TMEM_PUT_EPH);
++	unsigned long flags;
++	int ret;
++
++	xh = (struct tmem_xhandle *)p;
++	p += sizeof(struct tmem_xhandle);
++	zcache_autocreate_pool(xh->client_id, xh->pool_id, ephemeral);
++	local_irq_save(flags);
++	ret = zcache_put(xh->client_id, xh->pool_id, &xh->oid, xh->index,
++				p, datalen, 1, ephemeral ? 1 : -1);
++	local_irq_restore(flags);
++	return ret;
++}
++
++int ramster_remote_flush_handler(struct o2net_msg *msg,
++				u32 len, void *data, void **ret_data)
++{
++	struct tmem_xhandle *xh;
++	char *p = (char *)msg->buf;
++
++	xh = (struct tmem_xhandle *)p;
++	p += sizeof(struct tmem_xhandle);
++	(void)zcache_flush(xh->client_id, xh->pool_id, &xh->oid, xh->index);
++	return 0;
++}
++
++int ramster_remote_flobj_handler(struct o2net_msg *msg,
++				u32 len, void *data, void **ret_data)
++{
++	struct tmem_xhandle *xh;
++	char *p = (char *)msg->buf;
++
++	xh = (struct tmem_xhandle *)p;
++	p += sizeof(struct tmem_xhandle);
++	(void)zcache_flush_object(xh->client_id, xh->pool_id, &xh->oid);
++	return 0;
++}
++
++int ramster_remote_async_get(struct tmem_xhandle *xh, bool free, int remotenode,
++				size_t expect_size, uint8_t expect_cksum,
++				void *extra)
++{
++	int ret = -1, status;
++	struct o2nm_node *node = NULL;
++	struct kvec vec[1];
++	size_t veclen = 1;
++	u32 msg_type;
++
++	node = o2nm_get_node_by_num(remotenode);
++	if (node == NULL)
++		goto out;
++	xh->client_id = o2nm_this_node(); /* which node is getting */
++	xh->xh_data_cksum = expect_cksum;
++	xh->xh_data_size = expect_size;
++	xh->extra = extra;
++	vec[0].iov_len = sizeof(*xh);
++	vec[0].iov_base = xh;
++	if (free)
++		msg_type = RMSTR_TMEM_ASYNC_GET_AND_FREE_REQUEST;
++	else
++		msg_type = RMSTR_TMEM_ASYNC_GET_REQUEST;
++	ret = o2net_send_message_vec(msg_type, RMSTR_KEY,
++					vec, veclen, remotenode, &status);
++	ramster_put_node(node);
++	if (ret < 0) {
++		/* FIXME handle bad message possibilities here? */
++		pr_err("UNTESTED ret<0 in ramster_remote_async_get\n");
++	}
++	ret = status;
++out:
++	return ret;
++}
++
++int ramster_remote_put(struct tmem_xhandle *xh, char *data, size_t size,
++				bool ephemeral, int *remotenode)
++{
++	int nodenum, ret = -1, status;
++	struct o2nm_node *node = NULL;
++	struct kvec vec[2];
++	size_t veclen = 2;
++	u32 msg_type;
++
++	BUG_ON(size > RMSTR_O2NET_MAX_LEN);
++	xh->client_id = o2nm_this_node(); /* which node is putting */
++	vec[0].iov_len = sizeof(*xh);
++	vec[0].iov_base = xh;
++	vec[1].iov_len = size;
++	vec[1].iov_base = data;
++	node = ramster_choose_node(&nodenum, xh);
++	if (!node)
++		goto out;
++
++#if 1
++{
++	extern struct o2net_node *o2net_nn_from_num(u8);
++	struct o2net_node *nn = o2net_nn_from_num(nodenum);
++	WARN_ON_ONCE(nn->nn_persistent_error || !nn->nn_sc_valid);
++}
++#endif
++
++	if (ephemeral)
++		msg_type = RMSTR_TMEM_PUT_EPH;
++	else
++		msg_type = RMSTR_TMEM_PUT_PERS;
++#if 1
++/* leave me here to see if it catches a weird crash I've seen a couple times */
++{
++static int last_hardirq_cnt, last_softirq_cnt, last_preempt_cnt;
++int cur_hardirq_cnt, cur_softirq_cnt, cur_preempt_cnt;
++cur_hardirq_cnt = hardirq_count() >> HARDIRQ_SHIFT;
++if (cur_hardirq_cnt > last_hardirq_cnt) {
++	last_hardirq_cnt = cur_hardirq_cnt;
++	if (!(last_hardirq_cnt&(last_hardirq_cnt-1)))
++		pr_err("TESTING RRP hardirq_count=%d\n", last_hardirq_cnt);
++}
++cur_softirq_cnt = softirq_count() >> SOFTIRQ_SHIFT;
++if (cur_softirq_cnt > last_softirq_cnt) {
++	last_softirq_cnt = cur_softirq_cnt;
++	if (!(last_softirq_cnt&(last_softirq_cnt-1)))
++		pr_err("TESTING RRP softirq_count=%d\n", last_softirq_cnt);
++}
++cur_preempt_cnt = preempt_count() & PREEMPT_MASK;
++if (cur_preempt_cnt > last_preempt_cnt) {
++	last_preempt_cnt = cur_preempt_cnt;
++	if (!(last_preempt_cnt&(last_preempt_cnt-1)))
++		pr_err("TESTING RRP preempt_count=%d\n", last_preempt_cnt);
++}
++}
++#endif
++
++	ret = o2net_send_message_vec(msg_type, RMSTR_KEY,
++						vec, veclen, nodenum, &status);
++#if 1
++	if (ret != 0) {
++		pr_err("UNTESTED case in ramster_remote_put\n");
++		ret = -1;
++	}
++#endif
++	if (ret < 0)
++		ret = -1;
++	else {
++		ret = status;
++		*remotenode = nodenum;
++	}
++
++	ramster_put_node(node);
++out:
++	return ret;
++}
++
++int ramster_remote_flush(struct tmem_xhandle *xh, int remotenode)
++{
++	int ret = -1, status;
++	struct o2nm_node *node = NULL;
++	struct kvec vec[1];
++	size_t veclen = 1;
++
++	node = o2nm_get_node_by_num(remotenode);
++	BUG_ON(node == NULL);
++	xh->client_id = o2nm_this_node(); /* which node is flushing */
++	vec[0].iov_len = sizeof(*xh);
++	vec[0].iov_base = xh;
++	BUG_ON(irqs_disabled());
++	BUG_ON(in_softirq());
++	ret = o2net_send_message_vec(RMSTR_TMEM_FLUSH, RMSTR_KEY,
++					vec, veclen, remotenode, &status);
++	ramster_put_node(node);
++	return ret;
++}
++
++int ramster_remote_flush_object(struct tmem_xhandle *xh, int remotenode)
++{
++	int ret = -1, status;
++	struct o2nm_node *node = NULL;
++	struct kvec vec[1];
++	size_t veclen = 1;
++
++	node = o2nm_get_node_by_num(remotenode);
++	BUG_ON(node == NULL);
++	xh->client_id = o2nm_this_node(); /* which node is flobjing */
++	vec[0].iov_len = sizeof(*xh);
++	vec[0].iov_base = xh;
++	ret = o2net_send_message_vec(RMSTR_TMEM_FLOBJ, RMSTR_KEY,
++					vec, veclen, remotenode, &status);
++	ramster_put_node(node);
++	return ret;
++}
++
++/*
++ * Handler registration
++ */
++
++static LIST_HEAD(ramster_o2net_unreg_list);
++
++static void ramster_o2net_unregister_handlers(void)
++{
++	o2net_unregister_handler_list(&ramster_o2net_unreg_list);
++}
++
++int ramster_o2net_register_handlers(void)
++{
++	int status;
++
++	status = o2net_register_handler(RMSTR_TMEM_PUT_EPH, RMSTR_KEY,
++				RMSTR_O2NET_MAX_LEN,
++				ramster_remote_put_handler,
++				NULL, NULL, &ramster_o2net_unreg_list);
++	if (status)
++		goto bail;
++
++	status = o2net_register_handler(RMSTR_TMEM_PUT_PERS, RMSTR_KEY,
++				RMSTR_O2NET_MAX_LEN,
++				ramster_remote_put_handler,
++				NULL, NULL, &ramster_o2net_unreg_list);
++	if (status)
++		goto bail;
++
++	status = o2net_register_handler(RMSTR_TMEM_ASYNC_GET_REQUEST, RMSTR_KEY,
++				RMSTR_O2NET_MAX_LEN,
++				ramster_remote_async_get_request_handler,
++				NULL, NULL,
++				&ramster_o2net_unreg_list);
++	if (status)
++		goto bail;
++
++	status = o2net_register_handler(RMSTR_TMEM_ASYNC_GET_AND_FREE_REQUEST,
++				RMSTR_KEY, RMSTR_O2NET_MAX_LEN,
++				ramster_remote_async_get_request_handler,
++				NULL, NULL,
++				&ramster_o2net_unreg_list);
++	if (status)
++		goto bail;
++
++	status = o2net_register_handler(RMSTR_TMEM_ASYNC_GET_REPLY, RMSTR_KEY,
++				RMSTR_O2NET_MAX_LEN,
++				ramster_remote_async_get_reply_handler,
++				NULL, NULL,
++				&ramster_o2net_unreg_list);
++	if (status)
++		goto bail;
++
++	status = o2net_register_handler(RMSTR_TMEM_FLUSH, RMSTR_KEY,
++				RMSTR_O2NET_MAX_LEN,
++				ramster_remote_flush_handler,
++				NULL, NULL,
++				&ramster_o2net_unreg_list);
++	if (status)
++		goto bail;
++
++	status = o2net_register_handler(RMSTR_TMEM_FLOBJ, RMSTR_KEY,
++				RMSTR_O2NET_MAX_LEN,
++				ramster_remote_flobj_handler,
++				NULL, NULL,
++				&ramster_o2net_unreg_list);
++	if (status)
++		goto bail;
++
++	pr_info("ramster_o2net: handlers registered\n");
++
++bail:
++	if (status) {
++		ramster_o2net_unregister_handlers();
++		pr_err("ramster_o2net: couldn't register handlers\n");
++	}
++	return status;
++}
+diff --git a/drivers/staging/ramster/zcache.h b/drivers/staging/ramster/zcache.h
+new file mode 100644
+index 0000000..250b121
+--- /dev/null
++++ b/drivers/staging/ramster/zcache.h
+@@ -0,0 +1,22 @@
++/*
++ * zcache.h
++ *
++ * External zcache functions
++ *
++ * Copyright (c) 2009-2012, Dan Magenheimer, Oracle Corp.
++ */
++
++#ifndef _ZCACHE_H_
++#define _ZCACHE_H_
++
++extern int zcache_put(int, int, struct tmem_oid *, uint32_t,
++			char *, size_t, bool, int);
++extern int zcache_autocreate_pool(int, int, bool);
++extern int zcache_get(int, int, struct tmem_oid *, uint32_t,
++			char *, size_t *, bool, int);
++extern int zcache_flush(int, int, struct tmem_oid *, uint32_t);
++extern int zcache_flush_object(int, int, struct tmem_oid *);
++extern int zcache_localify(int, struct tmem_oid *, uint32_t,
++			char *, size_t, void *);
++
++#endif /* _ZCACHE_H */
+-- 
+1.7.1
diff --git a/a/content_digest b/N1/content_digest
index 2640ad1..ce3f21b 100644
--- a/a/content_digest
+++ b/N1/content_digest
@@ -13,5 +13,605 @@
  " dan.magenheimer@oracle.com\0"
  "\00:1\0"
  "b\0"
+ ">From 3a84584164119d3c08b2857fe45313cbd4df9a00 Mon Sep 17 00:00:00 2001\n"
+ "From: Dan Magenheimer <dan.magenheimer@oracle.com>\n"
+ "Date: Wed, 21 Dec 2011 14:02:01 -0700\n"
+ "Subject: [PATCH V2 5/6] drivers/staging/ramster: ramster-specific new files\n"
+ "\n"
+ "New files for ramster support:  The file ramster.h declares externs\n"
+ "and some pampd bitfield manipulation.  The file zcache.h declares\n"
+ "some zcache functions that now must be accessed from the ramster\n"
+ "glue code.  The file ramster_o2net.c is the glue between\n"
+ "zcache and the o2net messaging code, providing routines called\n"
+ "from zcache that initiate messages, and routines that handle\n"
+ "messages by calling zcache.\n"
+ "\n"
+ "Signed-off-by: Dan Magenheimer <dan.magenheimer@oracle.com>\n"
+ "\n"
+ "---\n"
+ "\n"
+ " drivers/staging/ramster/ramster.h       |  117 +++++++++\n"
+ " drivers/staging/ramster/ramster_o2net.c |  419 +++++++++++++++++++++++++++++++\n"
+ " drivers/staging/ramster/zcache.h        |   22 ++\n"
+ " 3 files changed, 558 insertions(+), 0 deletions(-)\n"
+ "\n"
+ "diff --git a/drivers/staging/ramster/ramster.h b/drivers/staging/ramster/ramster.h\n"
+ "new file mode 100644\n"
+ "index 0000000..3293512\n"
+ "--- /dev/null\n"
+ "+++ b/drivers/staging/ramster/ramster.h\n"
+ "@@ -0,0 +1,117 @@\n"
+ "+/*\n"
+ "+ * ramster.h\n"
+ "+ *\n"
+ "+ * Peer-to-peer transcendent memory\n"
+ "+ *\n"
+ "+ * Copyright (c) 2009-2012, Dan Magenheimer, Oracle Corp.\n"
+ "+ */\n"
+ "+\n"
+ "+#ifndef _RAMSTER_H_\n"
+ "+#define _RAMSTER_H_\n"
+ "+\n"
+ "+/*\n"
+ "+ * format of remote pampd:\n"
+ "+ *   bit 0 == intransit\n"
+ "+ *   bit 1 == is_remote... if this bit is set, then\n"
+ "+ *   bit 2-9 == remotenode\n"
+ "+ *   bit 10-22 == size\n"
+ "+ *   bit 23-30 == cksum\n"
+ "+ */\n"
+ "+#define FAKE_PAMPD_INTRANSIT_BITS\t1\n"
+ "+#define FAKE_PAMPD_ISREMOTE_BITS\t1\n"
+ "+#define FAKE_PAMPD_REMOTENODE_BITS\t8\n"
+ "+#define FAKE_PAMPD_REMOTESIZE_BITS\t13\n"
+ "+#define FAKE_PAMPD_CHECKSUM_BITS\t8\n"
+ "+\n"
+ "+#define FAKE_PAMPD_INTRANSIT_SHIFT\t0\n"
+ "+#define FAKE_PAMPD_ISREMOTE_SHIFT\t(FAKE_PAMPD_INTRANSIT_SHIFT + \\\n"
+ "+\t\t\t\t\t FAKE_PAMPD_INTRANSIT_BITS)\n"
+ "+#define FAKE_PAMPD_REMOTENODE_SHIFT\t(FAKE_PAMPD_ISREMOTE_SHIFT + \\\n"
+ "+\t\t\t\t\t FAKE_PAMPD_ISREMOTE_BITS)\n"
+ "+#define FAKE_PAMPD_REMOTESIZE_SHIFT\t(FAKE_PAMPD_REMOTENODE_SHIFT + \\\n"
+ "+\t\t\t\t\t FAKE_PAMPD_REMOTENODE_BITS)\n"
+ "+#define FAKE_PAMPD_CHECKSUM_SHIFT\t(FAKE_PAMPD_REMOTESIZE_SHIFT + \\\n"
+ "+\t\t\t\t\t FAKE_PAMPD_REMOTESIZE_BITS)\n"
+ "+\n"
+ "+#define FAKE_PAMPD_MASK(x)\t\t((1UL << (x)) - 1)\n"
+ "+\n"
+ "+static inline void *pampd_make_remote(int remotenode, size_t size,\n"
+ "+\t\t\t\t\tunsigned char cksum)\n"
+ "+{\n"
+ "+\tunsigned long fake_pampd = 0;\n"
+ "+\tfake_pampd |= 1UL << FAKE_PAMPD_ISREMOTE_SHIFT;\n"
+ "+\tfake_pampd |= ((unsigned long)remotenode &\n"
+ "+\t\t\tFAKE_PAMPD_MASK(FAKE_PAMPD_REMOTENODE_BITS)) <<\n"
+ "+\t\t\t\tFAKE_PAMPD_REMOTENODE_SHIFT;\n"
+ "+\tfake_pampd |= ((unsigned long)size &\n"
+ "+\t\t\tFAKE_PAMPD_MASK(FAKE_PAMPD_REMOTESIZE_BITS)) <<\n"
+ "+\t\t\t\tFAKE_PAMPD_REMOTESIZE_SHIFT;\n"
+ "+\tfake_pampd |= ((unsigned long)cksum &\n"
+ "+\t\t\tFAKE_PAMPD_MASK(FAKE_PAMPD_CHECKSUM_BITS)) <<\n"
+ "+\t\t\t\tFAKE_PAMPD_CHECKSUM_SHIFT;\n"
+ "+\treturn (void *)fake_pampd;\n"
+ "+}\n"
+ "+\n"
+ "+static inline unsigned int pampd_remote_node(void *pampd)\n"
+ "+{\n"
+ "+\tunsigned long fake_pampd = (unsigned long)pampd;\n"
+ "+\treturn (fake_pampd >> FAKE_PAMPD_REMOTENODE_SHIFT) &\n"
+ "+\t\tFAKE_PAMPD_MASK(FAKE_PAMPD_REMOTENODE_BITS);\n"
+ "+}\n"
+ "+\n"
+ "+static inline unsigned int pampd_remote_size(void *pampd)\n"
+ "+{\n"
+ "+\tunsigned long fake_pampd = (unsigned long)pampd;\n"
+ "+\treturn (fake_pampd >> FAKE_PAMPD_REMOTESIZE_SHIFT) &\n"
+ "+\t\tFAKE_PAMPD_MASK(FAKE_PAMPD_REMOTESIZE_BITS);\n"
+ "+}\n"
+ "+\n"
+ "+static inline unsigned char pampd_remote_cksum(void *pampd)\n"
+ "+{\n"
+ "+\tunsigned long fake_pampd = (unsigned long)pampd;\n"
+ "+\treturn (fake_pampd >> FAKE_PAMPD_CHECKSUM_SHIFT) &\n"
+ "+\t\tFAKE_PAMPD_MASK(FAKE_PAMPD_CHECKSUM_BITS);\n"
+ "+}\n"
+ "+\n"
+ "+static inline bool pampd_is_remote(void *pampd)\n"
+ "+{\n"
+ "+\tunsigned long fake_pampd = (unsigned long)pampd;\n"
+ "+\treturn (fake_pampd >> FAKE_PAMPD_ISREMOTE_SHIFT) &\n"
+ "+\t\tFAKE_PAMPD_MASK(FAKE_PAMPD_ISREMOTE_BITS);\n"
+ "+}\n"
+ "+\n"
+ "+static inline bool pampd_is_intransit(void *pampd)\n"
+ "+{\n"
+ "+\tunsigned long fake_pampd = (unsigned long)pampd;\n"
+ "+\treturn (fake_pampd >> FAKE_PAMPD_INTRANSIT_SHIFT) &\n"
+ "+\t\tFAKE_PAMPD_MASK(FAKE_PAMPD_INTRANSIT_BITS);\n"
+ "+}\n"
+ "+\n"
+ "+/* note that it is a BUG for intransit to be set without isremote also set */\n"
+ "+static inline void *pampd_mark_intransit(void *pampd)\n"
+ "+{\n"
+ "+\tunsigned long fake_pampd = (unsigned long)pampd;\n"
+ "+\n"
+ "+\tfake_pampd |= 1UL << FAKE_PAMPD_ISREMOTE_SHIFT;\n"
+ "+\tfake_pampd |= 1UL << FAKE_PAMPD_INTRANSIT_SHIFT;\n"
+ "+\treturn (void *)fake_pampd;\n"
+ "+}\n"
+ "+\n"
+ "+static inline void *pampd_mask_intransit_and_remote(void *marked_pampd)\n"
+ "+{\n"
+ "+\tunsigned long pampd = (unsigned long)marked_pampd;\n"
+ "+\n"
+ "+\tpampd &= ~(1UL << FAKE_PAMPD_INTRANSIT_SHIFT);\n"
+ "+\tpampd &= ~(1UL << FAKE_PAMPD_ISREMOTE_SHIFT);\n"
+ "+\treturn (void *)pampd;\n"
+ "+}\n"
+ "+\n"
+ "+extern int ramster_remote_async_get(struct tmem_xhandle *,\n"
+ "+\t\t\t\tbool, int, size_t, uint8_t, void *extra);\n"
+ "+extern int ramster_remote_put(struct tmem_xhandle *, char *, size_t,\n"
+ "+\t\t\t\tbool, int *);\n"
+ "+extern int ramster_remote_flush(struct tmem_xhandle *, int);\n"
+ "+extern int ramster_remote_flush_object(struct tmem_xhandle *, int);\n"
+ "+extern int ramster_o2net_register_handlers(void);\n"
+ "+\n"
+ "+#endif /* _TMEM_H */\n"
+ "diff --git a/drivers/staging/ramster/ramster_o2net.c b/drivers/staging/ramster/ramster_o2net.c\n"
+ "new file mode 100644\n"
+ "index 0000000..ee6a9ed\n"
+ "--- /dev/null\n"
+ "+++ b/drivers/staging/ramster/ramster_o2net.c\n"
+ "@@ -0,0 +1,419 @@\n"
+ "+/*\n"
+ "+ * ramster_o2net.c\n"
+ "+ *\n"
+ "+ * Copyright (c) 2011, Dan Magenheimer, Oracle Corp.\n"
+ "+ *\n"
+ "+ * Ramster_o2net provides an interface between zcache and o2net.\n"
+ "+ *\n"
+ "+ * FIXME: support more than two nodes\n"
+ "+ */\n"
+ "+\n"
+ "+#include <linux/list.h>\n"
+ "+#include \"cluster/tcp.h\"\n"
+ "+#include \"cluster/nodemanager.h\"\n"
+ "+#include \"tmem.h\"\n"
+ "+#include \"zcache.h\"\n"
+ "+#include \"ramster.h\"\n"
+ "+\n"
+ "+#define RMSTR_KEY\t0x77347734\n"
+ "+\n"
+ "+enum {\n"
+ "+\tRMSTR_TMEM_PUT_EPH = 100,\n"
+ "+\tRMSTR_TMEM_PUT_PERS,\n"
+ "+\tRMSTR_TMEM_ASYNC_GET_REQUEST,\n"
+ "+\tRMSTR_TMEM_ASYNC_GET_AND_FREE_REQUEST,\n"
+ "+\tRMSTR_TMEM_ASYNC_GET_REPLY,\n"
+ "+\tRMSTR_TMEM_FLUSH,\n"
+ "+\tRMSTR_TMEM_FLOBJ,\n"
+ "+\tRMSTR_TMEM_DESTROY_POOL,\n"
+ "+};\n"
+ "+\n"
+ "+#define RMSTR_O2NET_MAX_LEN \\\n"
+ "+\t\t(O2NET_MAX_PAYLOAD_BYTES - sizeof(struct tmem_xhandle))\n"
+ "+\n"
+ "+#include \"cluster/tcp_internal.h\"\n"
+ "+\n"
+ "+static struct o2nm_node *ramster_choose_node(int *nodenum,\n"
+ "+\t\t\t\t\t\tstruct tmem_xhandle *xh)\n"
+ "+{\n"
+ "+\tstruct o2nm_node *node = NULL;\n"
+ "+\tint i;\n"
+ "+\n"
+ "+/* FIXME reproducibly pick a node based on xh that is NOT this node */\n"
+ "+\ti = o2nm_this_node();\n"
+ "+\ti = !i;\t\t/* FIXME ONLY FOR TWO NODES */\n"
+ "+\tnode = o2nm_get_node_by_num(i);\n"
+ "+\t\t/* WARNING: THIS DOES NOT CHECK TO ENSURE CONNECTED */\n"
+ "+\tif (node != NULL)\n"
+ "+\t\t*nodenum = i;\n"
+ "+\treturn node;\n"
+ "+}\n"
+ "+\n"
+ "+static void ramster_put_node(struct o2nm_node *node)\n"
+ "+{\n"
+ "+\to2nm_node_put(node);\n"
+ "+}\n"
+ "+\n"
+ "+/* FIXME following buffer should be per-cpu, protected by preempt_disable */\n"
+ "+static char ramster_async_get_buf[O2NET_MAX_PAYLOAD_BYTES];\n"
+ "+\n"
+ "+static int ramster_remote_async_get_request_handler(struct o2net_msg *msg,\n"
+ "+\t\t\t\tu32 len, void *data, void **ret_data)\n"
+ "+{\n"
+ "+\tchar *pdata;\n"
+ "+\tstruct tmem_xhandle xh;\n"
+ "+\tint found;\n"
+ "+\tsize_t size = RMSTR_O2NET_MAX_LEN;\n"
+ "+\tu16 msgtype = be16_to_cpu(msg->msg_type);\n"
+ "+\tbool get_and_free = (msgtype == RMSTR_TMEM_ASYNC_GET_AND_FREE_REQUEST);\n"
+ "+\tunsigned long flags;\n"
+ "+\n"
+ "+\txh = *(struct tmem_xhandle *)msg->buf;\n"
+ "+\tif (xh.xh_data_size > RMSTR_O2NET_MAX_LEN)\n"
+ "+\t\tBUG();\n"
+ "+\tpdata = ramster_async_get_buf;\n"
+ "+\t*(struct tmem_xhandle *)pdata = xh;\n"
+ "+\tpdata += sizeof(struct tmem_xhandle);\n"
+ "+\tlocal_irq_save(flags);\n"
+ "+\tfound = zcache_get(xh.client_id, xh.pool_id, &xh.oid, xh.index,\n"
+ "+\t\t\t\tpdata, &size, 1, get_and_free ? 1 : -1);\n"
+ "+\tlocal_irq_restore(flags);\n"
+ "+\tif (found < 0) {\n"
+ "+#if 0\n"
+ "+static unsigned long cnt;\n"
+ "+cnt++;\n"
+ "+if (!(cnt&(cnt-1)))\n"
+ "+pr_err(\"TESTING ArrgREQ zcache_get %s failed, assuming is this OK? cnt=%lu\\n\",\n"
+ "+\t(get_and_free) ? \"eph\" : \"pers\", cnt);\n"
+ "+#endif\n"
+ "+\t\t/* a zero size indicates the get failed */\n"
+ "+\t\tsize = 0;\n"
+ "+\t}\n"
+ "+\tif (size > RMSTR_O2NET_MAX_LEN)\n"
+ "+\t\tBUG();\n"
+ "+#if 0\n"
+ "+if (size != 0) {\n"
+ "+/* DOH! RMSTR_O2NET_MAX_LEN==4032... means zcache_get is returning failure\n"
+ "+   which means maybe a race with a flush? */\n"
+ "+unsigned char cksum;\n"
+ "+int i;\n"
+ "+char *tmp;\n"
+ "+for (tmp = pdata, cksum = 0, i = 0; i < size; i++)\n"
+ "+\tcksum += *tmp;\n"
+ "+if ((xh.xh_data_size != size) || (xh.xh_data_cksum != cksum))\n"
+ "+pr_err(\"TESTING ArrgREQ, HUH xh_data_size=%d, exp=%d, cksum=%d, exp=%d,\"\n"
+ "+\t\"xh=(%d,0x%llx.0x%llx.0x%llx,%x), %s\\n\",\n"
+ "+\t(int)xh.xh_data_size, (int)size, xh.xh_data_cksum, cksum,\n"
+ "+\txh.pool_id, xh.oid.oid[0], xh.oid.oid[1], xh.oid.oid[2],\n"
+ "+\txh.index, (get_and_free ? \"eph\" : \"pers\"));\n"
+ "+else {\n"
+ "+#if 0\n"
+ "+static unsigned long cnt;\n"
+ "+cnt++;\n"
+ "+if (!(cnt&(cnt-1)))\n"
+ "+pr_err(\"TESTING ArrgREQ cnt=%lu, xh_data_size=%d, exp=%d, cksum=%d, exp=%d\\n\",\n"
+ "+\tcnt, (int)xh.xh_data_size, (int)size, xh.xh_data_cksum, cksum);\n"
+ "+#endif\n"
+ "+}\n"
+ "+}\n"
+ "+#endif\n"
+ "+\t*ret_data = pdata - sizeof(struct tmem_xhandle);\n"
+ "+\t/* now make caller (o2net_process_message) handle specially */\n"
+ "+\to2net_force_data_magic(msg, RMSTR_TMEM_ASYNC_GET_REPLY, RMSTR_KEY);\n"
+ "+\treturn size + sizeof(struct tmem_xhandle);\n"
+ "+}\n"
+ "+\n"
+ "+static int ramster_remote_async_get_reply_handler(struct o2net_msg *msg,\n"
+ "+\t\t\t\tu32 len, void *data, void **ret_data)\n"
+ "+{\n"
+ "+\tchar *in = (char *)msg->buf;\n"
+ "+\tint datalen = len - sizeof(struct o2net_msg);\n"
+ "+\tint ret = -1;\n"
+ "+\tstruct tmem_xhandle *xh = (struct tmem_xhandle *)in;\n"
+ "+\n"
+ "+\tin += sizeof(struct tmem_xhandle);\n"
+ "+\tdatalen -= sizeof(struct tmem_xhandle);\n"
+ "+\tBUG_ON(datalen < 0 || datalen > PAGE_SIZE);\n"
+ "+\tret = zcache_localify(xh->pool_id, &xh->oid, xh->index,\n"
+ "+\t\t\t\tin, datalen, xh->extra);\n"
+ "+#if 1\n"
+ "+if (ret == -EEXIST)\n"
+ "+pr_err(\"TESTING ArrgREP, aborted overwrite on racy put\\n\");\n"
+ "+#endif\n"
+ "+\treturn ret;\n"
+ "+}\n"
+ "+\n"
+ "+int ramster_remote_put_handler(struct o2net_msg *msg,\n"
+ "+\t\t\t\tu32 len, void *data, void **ret_data)\n"
+ "+{\n"
+ "+\tstruct tmem_xhandle *xh;\n"
+ "+\tchar *p = (char *)msg->buf;\n"
+ "+\tint datalen = len - sizeof(struct o2net_msg) -\n"
+ "+\t\t\t\tsizeof(struct tmem_xhandle);\n"
+ "+\tu16 msgtype = be16_to_cpu(msg->msg_type);\n"
+ "+\tbool ephemeral = (msgtype == RMSTR_TMEM_PUT_EPH);\n"
+ "+\tunsigned long flags;\n"
+ "+\tint ret;\n"
+ "+\n"
+ "+\txh = (struct tmem_xhandle *)p;\n"
+ "+\tp += sizeof(struct tmem_xhandle);\n"
+ "+\tzcache_autocreate_pool(xh->client_id, xh->pool_id, ephemeral);\n"
+ "+\tlocal_irq_save(flags);\n"
+ "+\tret = zcache_put(xh->client_id, xh->pool_id, &xh->oid, xh->index,\n"
+ "+\t\t\t\tp, datalen, 1, ephemeral ? 1 : -1);\n"
+ "+\tlocal_irq_restore(flags);\n"
+ "+\treturn ret;\n"
+ "+}\n"
+ "+\n"
+ "+int ramster_remote_flush_handler(struct o2net_msg *msg,\n"
+ "+\t\t\t\tu32 len, void *data, void **ret_data)\n"
+ "+{\n"
+ "+\tstruct tmem_xhandle *xh;\n"
+ "+\tchar *p = (char *)msg->buf;\n"
+ "+\n"
+ "+\txh = (struct tmem_xhandle *)p;\n"
+ "+\tp += sizeof(struct tmem_xhandle);\n"
+ "+\t(void)zcache_flush(xh->client_id, xh->pool_id, &xh->oid, xh->index);\n"
+ "+\treturn 0;\n"
+ "+}\n"
+ "+\n"
+ "+int ramster_remote_flobj_handler(struct o2net_msg *msg,\n"
+ "+\t\t\t\tu32 len, void *data, void **ret_data)\n"
+ "+{\n"
+ "+\tstruct tmem_xhandle *xh;\n"
+ "+\tchar *p = (char *)msg->buf;\n"
+ "+\n"
+ "+\txh = (struct tmem_xhandle *)p;\n"
+ "+\tp += sizeof(struct tmem_xhandle);\n"
+ "+\t(void)zcache_flush_object(xh->client_id, xh->pool_id, &xh->oid);\n"
+ "+\treturn 0;\n"
+ "+}\n"
+ "+\n"
+ "+int ramster_remote_async_get(struct tmem_xhandle *xh, bool free, int remotenode,\n"
+ "+\t\t\t\tsize_t expect_size, uint8_t expect_cksum,\n"
+ "+\t\t\t\tvoid *extra)\n"
+ "+{\n"
+ "+\tint ret = -1, status;\n"
+ "+\tstruct o2nm_node *node = NULL;\n"
+ "+\tstruct kvec vec[1];\n"
+ "+\tsize_t veclen = 1;\n"
+ "+\tu32 msg_type;\n"
+ "+\n"
+ "+\tnode = o2nm_get_node_by_num(remotenode);\n"
+ "+\tif (node == NULL)\n"
+ "+\t\tgoto out;\n"
+ "+\txh->client_id = o2nm_this_node(); /* which node is getting */\n"
+ "+\txh->xh_data_cksum = expect_cksum;\n"
+ "+\txh->xh_data_size = expect_size;\n"
+ "+\txh->extra = extra;\n"
+ "+\tvec[0].iov_len = sizeof(*xh);\n"
+ "+\tvec[0].iov_base = xh;\n"
+ "+\tif (free)\n"
+ "+\t\tmsg_type = RMSTR_TMEM_ASYNC_GET_AND_FREE_REQUEST;\n"
+ "+\telse\n"
+ "+\t\tmsg_type = RMSTR_TMEM_ASYNC_GET_REQUEST;\n"
+ "+\tret = o2net_send_message_vec(msg_type, RMSTR_KEY,\n"
+ "+\t\t\t\t\tvec, veclen, remotenode, &status);\n"
+ "+\tramster_put_node(node);\n"
+ "+\tif (ret < 0) {\n"
+ "+\t\t/* FIXME handle bad message possibilities here? */\n"
+ "+\t\tpr_err(\"UNTESTED ret<0 in ramster_remote_async_get\\n\");\n"
+ "+\t}\n"
+ "+\tret = status;\n"
+ "+out:\n"
+ "+\treturn ret;\n"
+ "+}\n"
+ "+\n"
+ "+int ramster_remote_put(struct tmem_xhandle *xh, char *data, size_t size,\n"
+ "+\t\t\t\tbool ephemeral, int *remotenode)\n"
+ "+{\n"
+ "+\tint nodenum, ret = -1, status;\n"
+ "+\tstruct o2nm_node *node = NULL;\n"
+ "+\tstruct kvec vec[2];\n"
+ "+\tsize_t veclen = 2;\n"
+ "+\tu32 msg_type;\n"
+ "+\n"
+ "+\tBUG_ON(size > RMSTR_O2NET_MAX_LEN);\n"
+ "+\txh->client_id = o2nm_this_node(); /* which node is putting */\n"
+ "+\tvec[0].iov_len = sizeof(*xh);\n"
+ "+\tvec[0].iov_base = xh;\n"
+ "+\tvec[1].iov_len = size;\n"
+ "+\tvec[1].iov_base = data;\n"
+ "+\tnode = ramster_choose_node(&nodenum, xh);\n"
+ "+\tif (!node)\n"
+ "+\t\tgoto out;\n"
+ "+\n"
+ "+#if 1\n"
+ "+{\n"
+ "+\textern struct o2net_node *o2net_nn_from_num(u8);\n"
+ "+\tstruct o2net_node *nn = o2net_nn_from_num(nodenum);\n"
+ "+\tWARN_ON_ONCE(nn->nn_persistent_error || !nn->nn_sc_valid);\n"
+ "+}\n"
+ "+#endif\n"
+ "+\n"
+ "+\tif (ephemeral)\n"
+ "+\t\tmsg_type = RMSTR_TMEM_PUT_EPH;\n"
+ "+\telse\n"
+ "+\t\tmsg_type = RMSTR_TMEM_PUT_PERS;\n"
+ "+#if 1\n"
+ "+/* leave me here to see if it catches a weird crash I've seen a couple times */\n"
+ "+{\n"
+ "+static int last_hardirq_cnt, last_softirq_cnt, last_preempt_cnt;\n"
+ "+int cur_hardirq_cnt, cur_softirq_cnt, cur_preempt_cnt;\n"
+ "+cur_hardirq_cnt = hardirq_count() >> HARDIRQ_SHIFT;\n"
+ "+if (cur_hardirq_cnt > last_hardirq_cnt) {\n"
+ "+\tlast_hardirq_cnt = cur_hardirq_cnt;\n"
+ "+\tif (!(last_hardirq_cnt&(last_hardirq_cnt-1)))\n"
+ "+\t\tpr_err(\"TESTING RRP hardirq_count=%d\\n\", last_hardirq_cnt);\n"
+ "+}\n"
+ "+cur_softirq_cnt = softirq_count() >> SOFTIRQ_SHIFT;\n"
+ "+if (cur_softirq_cnt > last_softirq_cnt) {\n"
+ "+\tlast_softirq_cnt = cur_softirq_cnt;\n"
+ "+\tif (!(last_softirq_cnt&(last_softirq_cnt-1)))\n"
+ "+\t\tpr_err(\"TESTING RRP softirq_count=%d\\n\", last_softirq_cnt);\n"
+ "+}\n"
+ "+cur_preempt_cnt = preempt_count() & PREEMPT_MASK;\n"
+ "+if (cur_preempt_cnt > last_preempt_cnt) {\n"
+ "+\tlast_preempt_cnt = cur_preempt_cnt;\n"
+ "+\tif (!(last_preempt_cnt&(last_preempt_cnt-1)))\n"
+ "+\t\tpr_err(\"TESTING RRP preempt_count=%d\\n\", last_preempt_cnt);\n"
+ "+}\n"
+ "+}\n"
+ "+#endif\n"
+ "+\n"
+ "+\tret = o2net_send_message_vec(msg_type, RMSTR_KEY,\n"
+ "+\t\t\t\t\t\tvec, veclen, nodenum, &status);\n"
+ "+#if 1\n"
+ "+\tif (ret != 0) {\n"
+ "+\t\tpr_err(\"UNTESTED case in ramster_remote_put\\n\");\n"
+ "+\t\tret = -1;\n"
+ "+\t}\n"
+ "+#endif\n"
+ "+\tif (ret < 0)\n"
+ "+\t\tret = -1;\n"
+ "+\telse {\n"
+ "+\t\tret = status;\n"
+ "+\t\t*remotenode = nodenum;\n"
+ "+\t}\n"
+ "+\n"
+ "+\tramster_put_node(node);\n"
+ "+out:\n"
+ "+\treturn ret;\n"
+ "+}\n"
+ "+\n"
+ "+int ramster_remote_flush(struct tmem_xhandle *xh, int remotenode)\n"
+ "+{\n"
+ "+\tint ret = -1, status;\n"
+ "+\tstruct o2nm_node *node = NULL;\n"
+ "+\tstruct kvec vec[1];\n"
+ "+\tsize_t veclen = 1;\n"
+ "+\n"
+ "+\tnode = o2nm_get_node_by_num(remotenode);\n"
+ "+\tBUG_ON(node == NULL);\n"
+ "+\txh->client_id = o2nm_this_node(); /* which node is flushing */\n"
+ "+\tvec[0].iov_len = sizeof(*xh);\n"
+ "+\tvec[0].iov_base = xh;\n"
+ "+\tBUG_ON(irqs_disabled());\n"
+ "+\tBUG_ON(in_softirq());\n"
+ "+\tret = o2net_send_message_vec(RMSTR_TMEM_FLUSH, RMSTR_KEY,\n"
+ "+\t\t\t\t\tvec, veclen, remotenode, &status);\n"
+ "+\tramster_put_node(node);\n"
+ "+\treturn ret;\n"
+ "+}\n"
+ "+\n"
+ "+int ramster_remote_flush_object(struct tmem_xhandle *xh, int remotenode)\n"
+ "+{\n"
+ "+\tint ret = -1, status;\n"
+ "+\tstruct o2nm_node *node = NULL;\n"
+ "+\tstruct kvec vec[1];\n"
+ "+\tsize_t veclen = 1;\n"
+ "+\n"
+ "+\tnode = o2nm_get_node_by_num(remotenode);\n"
+ "+\tBUG_ON(node == NULL);\n"
+ "+\txh->client_id = o2nm_this_node(); /* which node is flobjing */\n"
+ "+\tvec[0].iov_len = sizeof(*xh);\n"
+ "+\tvec[0].iov_base = xh;\n"
+ "+\tret = o2net_send_message_vec(RMSTR_TMEM_FLOBJ, RMSTR_KEY,\n"
+ "+\t\t\t\t\tvec, veclen, remotenode, &status);\n"
+ "+\tramster_put_node(node);\n"
+ "+\treturn ret;\n"
+ "+}\n"
+ "+\n"
+ "+/*\n"
+ "+ * Handler registration\n"
+ "+ */\n"
+ "+\n"
+ "+static LIST_HEAD(ramster_o2net_unreg_list);\n"
+ "+\n"
+ "+static void ramster_o2net_unregister_handlers(void)\n"
+ "+{\n"
+ "+\to2net_unregister_handler_list(&ramster_o2net_unreg_list);\n"
+ "+}\n"
+ "+\n"
+ "+int ramster_o2net_register_handlers(void)\n"
+ "+{\n"
+ "+\tint status;\n"
+ "+\n"
+ "+\tstatus = o2net_register_handler(RMSTR_TMEM_PUT_EPH, RMSTR_KEY,\n"
+ "+\t\t\t\tRMSTR_O2NET_MAX_LEN,\n"
+ "+\t\t\t\tramster_remote_put_handler,\n"
+ "+\t\t\t\tNULL, NULL, &ramster_o2net_unreg_list);\n"
+ "+\tif (status)\n"
+ "+\t\tgoto bail;\n"
+ "+\n"
+ "+\tstatus = o2net_register_handler(RMSTR_TMEM_PUT_PERS, RMSTR_KEY,\n"
+ "+\t\t\t\tRMSTR_O2NET_MAX_LEN,\n"
+ "+\t\t\t\tramster_remote_put_handler,\n"
+ "+\t\t\t\tNULL, NULL, &ramster_o2net_unreg_list);\n"
+ "+\tif (status)\n"
+ "+\t\tgoto bail;\n"
+ "+\n"
+ "+\tstatus = o2net_register_handler(RMSTR_TMEM_ASYNC_GET_REQUEST, RMSTR_KEY,\n"
+ "+\t\t\t\tRMSTR_O2NET_MAX_LEN,\n"
+ "+\t\t\t\tramster_remote_async_get_request_handler,\n"
+ "+\t\t\t\tNULL, NULL,\n"
+ "+\t\t\t\t&ramster_o2net_unreg_list);\n"
+ "+\tif (status)\n"
+ "+\t\tgoto bail;\n"
+ "+\n"
+ "+\tstatus = o2net_register_handler(RMSTR_TMEM_ASYNC_GET_AND_FREE_REQUEST,\n"
+ "+\t\t\t\tRMSTR_KEY, RMSTR_O2NET_MAX_LEN,\n"
+ "+\t\t\t\tramster_remote_async_get_request_handler,\n"
+ "+\t\t\t\tNULL, NULL,\n"
+ "+\t\t\t\t&ramster_o2net_unreg_list);\n"
+ "+\tif (status)\n"
+ "+\t\tgoto bail;\n"
+ "+\n"
+ "+\tstatus = o2net_register_handler(RMSTR_TMEM_ASYNC_GET_REPLY, RMSTR_KEY,\n"
+ "+\t\t\t\tRMSTR_O2NET_MAX_LEN,\n"
+ "+\t\t\t\tramster_remote_async_get_reply_handler,\n"
+ "+\t\t\t\tNULL, NULL,\n"
+ "+\t\t\t\t&ramster_o2net_unreg_list);\n"
+ "+\tif (status)\n"
+ "+\t\tgoto bail;\n"
+ "+\n"
+ "+\tstatus = o2net_register_handler(RMSTR_TMEM_FLUSH, RMSTR_KEY,\n"
+ "+\t\t\t\tRMSTR_O2NET_MAX_LEN,\n"
+ "+\t\t\t\tramster_remote_flush_handler,\n"
+ "+\t\t\t\tNULL, NULL,\n"
+ "+\t\t\t\t&ramster_o2net_unreg_list);\n"
+ "+\tif (status)\n"
+ "+\t\tgoto bail;\n"
+ "+\n"
+ "+\tstatus = o2net_register_handler(RMSTR_TMEM_FLOBJ, RMSTR_KEY,\n"
+ "+\t\t\t\tRMSTR_O2NET_MAX_LEN,\n"
+ "+\t\t\t\tramster_remote_flobj_handler,\n"
+ "+\t\t\t\tNULL, NULL,\n"
+ "+\t\t\t\t&ramster_o2net_unreg_list);\n"
+ "+\tif (status)\n"
+ "+\t\tgoto bail;\n"
+ "+\n"
+ "+\tpr_info(\"ramster_o2net: handlers registered\\n\");\n"
+ "+\n"
+ "+bail:\n"
+ "+\tif (status) {\n"
+ "+\t\tramster_o2net_unregister_handlers();\n"
+ "+\t\tpr_err(\"ramster_o2net: couldn't register handlers\\n\");\n"
+ "+\t}\n"
+ "+\treturn status;\n"
+ "+}\n"
+ "diff --git a/drivers/staging/ramster/zcache.h b/drivers/staging/ramster/zcache.h\n"
+ "new file mode 100644\n"
+ "index 0000000..250b121\n"
+ "--- /dev/null\n"
+ "+++ b/drivers/staging/ramster/zcache.h\n"
+ "@@ -0,0 +1,22 @@\n"
+ "+/*\n"
+ "+ * zcache.h\n"
+ "+ *\n"
+ "+ * External zcache functions\n"
+ "+ *\n"
+ "+ * Copyright (c) 2009-2012, Dan Magenheimer, Oracle Corp.\n"
+ "+ */\n"
+ "+\n"
+ "+#ifndef _ZCACHE_H_\n"
+ "+#define _ZCACHE_H_\n"
+ "+\n"
+ "+extern int zcache_put(int, int, struct tmem_oid *, uint32_t,\n"
+ "+\t\t\tchar *, size_t, bool, int);\n"
+ "+extern int zcache_autocreate_pool(int, int, bool);\n"
+ "+extern int zcache_get(int, int, struct tmem_oid *, uint32_t,\n"
+ "+\t\t\tchar *, size_t *, bool, int);\n"
+ "+extern int zcache_flush(int, int, struct tmem_oid *, uint32_t);\n"
+ "+extern int zcache_flush_object(int, int, struct tmem_oid *);\n"
+ "+extern int zcache_localify(int, struct tmem_oid *, uint32_t,\n"
+ "+\t\t\tchar *, size_t, void *);\n"
+ "+\n"
+ "+#endif /* _ZCACHE_H */\n"
+ "-- \n"
+ 1.7.1
 
-1c9373857f7e247d87a108efe2a2a79ad02dd1a3a1d2fa10c20823bfd975a4fe
+1f612b970982819a5a77fe7feacaa239b2afe1909d00564648940677d1170eb8

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.