*
* (c) Peter Dinda, 2011 (interface, mem + file implementations + recooked user impl)
* (c) Clint Sbisa, 2011 (initial user space implementation on which this is based)
+ * (c) Diana Palsetia & Steve Rangel, 2012 (network based implementation)
*/
#include <linux/fs.h>
#include "iface-keyed-stream-user.h"
+#include <interfaces/vmm_socket.h>
+
+#include <linux/spinlock.h>
+#include <asm/uaccess.h>
+#include <linux/inet.h>
+#include <linux/kthread.h>
+#include <linux/netdevice.h>
+#include <linux/ip.h>
+#include <linux/in.h>
+#include <linux/string.h>
+#include <linux/preempt.h>
+#include <linux/sched.h>
+#include <linux/list.h>
+#include <linux/syscalls.h>
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/socket.h>
+#include <linux/net.h>
+#include <linux/slab.h>
+
+
/*
This is an implementation of the Palacios keyed stream interface
- that supports three flavors of streams:
+ that supports four flavors of streams:
"mem:" Streams are stored in a hash table
The values for this hash table are hash tables associated with
each stream.
"file:" Streams are stored in files. Each high-level
- open corresponds to a directory, while key corresponds to
+ open corresponds to a directory, while a key corresponds to
a distinct file in that directory.
+ "net:" Streams are carried over the network. Each
+ high level open corresponds to a TCP connection, while
+ each key corresponds to a context on the stream.
+ "net:a:<ip>:<port>" => Bind to <ip>:<port> and accept a connection
+ "net:c:<ip>:<port>" => Connect to <ip>:<port>
+
"user:" Stream requests are bounced to user space to be
handled there. A rendezvous approach similar to the host
device userland support is used
#define STREAM_MEM 1
#define STREAM_FILE 2
#define STREAM_USER 3
+#define STREAM_NETWORK 4
/*
All keyed streams and streams indicate their implementation type within the first field
static struct mem_stream *create_mem_stream_internal(uint64_t size)
{
- struct mem_stream *m = kmalloc(sizeof(struct mem_stream),GFP_KERNEL);
+ struct mem_stream *m = palacios_alloc(sizeof(struct mem_stream));
if (!m) {
return 0;
m->data = vmalloc(size);
if (!m->data) {
- kfree(m);
+ palacios_free(m);
return 0;
}
{
if (m) {
if (m->data) {
- kfree(m->data);
+ vfree(m->data);
}
m->data=0;
- kfree(m);
+ palacios_free(m);
}
}
memcpy(data,m->data,nc);
- kfree(m->data);
+ vfree(m->data);
m->data=data;
m->size=new_size;
{
if (strncasecmp(url,"mem:",4)) {
- printk("palacios: illegitimate attempt to open memory stream \"%s\"\n",url);
+ WARNING("illegitimate attempt to open memory stream \"%s\"\n",url);
return 0;
}
if (!mks) {
char *mykey;
- mykey = kmalloc(strlen(url+4)+1,GFP_KERNEL);
+ mykey = palacios_alloc(strlen(url+4)+1);
if (!mykey) {
- printk("palacios: cannot allocate space for new in-memory keyed stream %s\n",url);
+ ERROR("cannot allocate space for new in-memory keyed stream %s\n",url);
return 0;
}
strcpy(mykey,url+4);
- mks = (struct mem_keyed_stream *) kmalloc(sizeof(struct mem_keyed_stream),GFP_KERNEL);
+ mks = (struct mem_keyed_stream *) palacios_alloc(sizeof(struct mem_keyed_stream));
if (!mks) {
- kfree(mykey);
- printk("palacios: cannot allocate in-memory keyed stream %s\n",url);
+ palacios_free(mykey);
+ ERROR("cannot allocate in-memory keyed stream %s\n",url);
return 0;
}
mks->ht = (void*) palacios_create_htable(DEF_NUM_KEYS,hash_func,hash_comp);
if (!mks->ht) {
- kfree(mks);
- kfree(mykey);
- printk("palacios: cannot allocate in-memory keyed stream %s\n",url);
+ palacios_free(mks);
+ palacios_free(mykey);
+ ERROR("cannot allocate in-memory keyed stream %s\n",url);
return 0;
}
if (!palacios_htable_insert(mem_streams,(addr_t)(mykey),(addr_t)mks)) {
palacios_free_htable(mks->ht,1,1);
- kfree(mks);
- kfree(mykey);
- printk("palacios: cannot insert in-memory keyed stream %s\n",url);
+ palacios_free(mks);
+ palacios_free(mykey);
+ ERROR("cannot insert in-memory keyed stream %s\n",url);
return 0;
}
mks->stype=STREAM_MEM;
break;
default:
- printk("palacios: unsupported open type in open_stream_mem\n");
+ ERROR("unsupported open type in open_stream_mem\n");
break;
}
m = (struct mem_stream *) palacios_htable_search(s,(addr_t)key);
if (!m) {
- char *mykey = kmalloc(strlen(key)+1,GFP_KERNEL);
+ char *mykey = palacios_alloc(strlen(key)+1);
if (!mykey) {
- printk("palacios: cannot allocate copy of key for key %s\n",key);
+ ERROR("cannot allocate copy of key for key %s\n",key);
return 0;
}
m = create_mem_stream();
if (!m) {
- kfree(mykey);
- printk("palacios: cannot allocate mem keyed stream for key %s\n",key);
+ palacios_free(mykey);
+ ERROR("cannot allocate mem keyed stream for key %s\n",key);
return 0;
}
if (!palacios_htable_insert(s,(addr_t)mykey,(addr_t)m)) {
destroy_mem_stream(m);
- kfree(mykey);
- printk("palacios: cannot insert mem keyed stream for key %s\n",key);
+ palacios_free(mykey);
+ ERROR("cannot insert mem keyed stream for key %s\n",key);
return 0;
}
}
if (!m) {
char *mykey;
- mykey=kmalloc(strlen(key)+1,GFP_KERNEL);
+ mykey=palacios_alloc(strlen(key)+1);
if (!mykey) {
- printk("palacios: cannot allocate key spce for preallocte for key %s\n",key);
+ ERROR("cannot allocate key space for preallocte for key %s\n",key);
return;
}
m = create_mem_stream_internal(size);
if (!m) {
- printk("palacios: cannot preallocate mem keyed stream for key %s\n",key);
+ ERROR("cannot preallocate mem keyed stream for key %s\n",key);
return;
}
if (!palacios_htable_insert(s,(addr_t)mykey,(addr_t)m)) {
- printk("palacios: cannot insert preallocated mem keyed stream for key %s\n",key);
+ ERROR("cannot insert preallocated mem keyed stream for key %s\n",key);
destroy_mem_stream(m);
return;
}
} else {
if (m->data_max < size) {
if (expand_mem_stream(m,size)) {
- printk("palacios: cannot expand key for preallocation for key %s\n",key);
+ ERROR("cannot expand key for preallocation for key %s\n",key);
return;
}
}
writelen=write_mem_stream(m,buf,mylen);
if (writelen!=mylen) {
- printk("palacios: failed to write all data for key\n");
+ ERROR("failed to write all data for key\n");
return -1;
} else {
return (sint64_t)writelen;
readlen=read_mem_stream(m,buf,mylen);
if (readlen!=mylen) {
- printk("palacios: failed to read all data for key\n");
+ ERROR("failed to read all data for key\n");
return -1;
} else {
return (sint64_t)readlen;
struct nameidata nd;
if (strncasecmp(url,"file:",5)) {
- printk("palacios: illegitimate attempt to open file stream \"%s\"\n",url);
+ WARNING("illegitimate attempt to open file stream \"%s\"\n",url);
return 0;
}
- fks = kmalloc(sizeof(struct file_keyed_stream),GFP_KERNEL);
+ fks = palacios_alloc(sizeof(struct file_keyed_stream));
if (!fks) {
- printk("palacios: cannot allocate space for file stream\n");
+ ERROR("cannot allocate space for file stream\n");
return 0;
}
- fks->path = (char*)kmalloc(strlen(url+5)+1,GFP_KERNEL);
+ fks->path = (char*)palacios_alloc(strlen(url+5)+1);
if (!(fks->path)) {
- printk("palacios: cannot allocate space for file stream\n");
- kfree(fks);
+ ERROR("cannot allocate space for file stream\n");
+ palacios_free(fks);
return 0;
}
if (ot==V3_KS_RD_ONLY || ot==V3_KS_WR_ONLY) {
// we are not being asked to create it
- printk("palacios: attempt to open %s, which does not exist\n",fks->path);
+ ERROR("attempt to open %s, which does not exist\n",fks->path);
goto fail_out;
} else {
// Find its parent
if (path_lookup(fks->path,LOOKUP_PARENT|LOOKUP_FOLLOW,&nd)) {
- printk("palacios: attempt to create %s failed because its parent cannot be looked up\n",fks->path);
+ ERROR("attempt to create %s failed because its parent cannot be looked up\n",fks->path);
goto fail_out;
}
// Can we write to the parent?
if (inode_permission(nd.path.dentry->d_inode, MAY_WRITE | MAY_EXEC)) {
- printk("palacios: attempt to open %s, which has the wrong permissions for directory creation\n",fks->path);
+ ERROR("attempt to open %s, which has the wrong permissions for directory creation\n",fks->path);
goto fail_out;
}
de = lookup_create(&nd,1);
if (IS_ERR(de)) {
- printk("palacios: cannot allocate dentry\n");
+ ERROR("cannot allocate dentry\n");
goto fail_out;
}
mutex_unlock(&(nd.path.dentry->d_inode->i_mutex));
if (err) {
- printk("palacios: attempt to create %s failed because mkdir failed\n",fks->path);
+ ERROR("attempt to create %s failed because mkdir failed\n",fks->path);
goto fail_out;
}
// and the directory exists, so we must check the permissions
if (inode_permission(nd.path.dentry->d_inode, MAY_EXEC | (ot==V3_KS_RD_ONLY ? MAY_READ : MAY_WRITE))) {
- printk("palacios: attempt to open %s, which has the wrong permissions\n",fks->path);
+ ERROR("attempt to open %s, which has the wrong permissions\n",fks->path);
goto fail_out;
} else {
return (v3_keyed_stream_t) fks;
fail_out:
- kfree(fks->path);
- kfree(fks);
+ palacios_free(fks->path);
+ palacios_free(fks);
return 0;
}
{
struct file_keyed_stream *fks = (struct file_keyed_stream *) stream;
- kfree(fks->path);
- kfree(fks);
+ palacios_free(fks->path);
+ palacios_free(fks);
}
// the path is the stream's path plus the key name
// file:/home/foo + "regext" => "/home/foo/regext"
- path = (char *) kmalloc(strlen(fks->path)+strlen(key)+2,GFP_KERNEL);
+ path = (char *) palacios_alloc(strlen(fks->path)+strlen(key)+2);
if (!path) {
- printk("palacios: cannot allocate file keyed stream for key %s\n",key);
+ ERROR("cannot allocate file keyed stream for key %s\n",key);
return 0;
}
strcpy(path,fks->path);
strcat(path,"/");
strcat(path,key);
- fs = (struct file_stream *) kmalloc(sizeof(struct file_stream *),GFP_KERNEL);
+ fs = (struct file_stream *) palacios_alloc(sizeof(struct file_stream *));
if (!fs) {
- printk("palacios: cannot allocate file keyed stream for key %s\n",key);
- kfree(path);
+ ERROR("cannot allocate file keyed stream for key %s\n",key);
+ palacios_free(path);
return 0;
}
fs->f = filp_open(path,O_RDWR|O_CREAT,0600);
if (IS_ERR(fs->f)) {
- printk("palacios: cannot open relevent file \"%s\" for stream \"file:%s\" and key \"%s\"\n",path,fks->path,key);
- kfree(fs);
- kfree(path);
+ ERROR("cannot open relevent file \"%s\" for stream \"file:%s\" and key \"%s\"\n",path,fks->path,key);
+ palacios_free(fs);
+ palacios_free(path);
return 0;
}
- kfree(path);
+ palacios_free(path);
return fs;
}
filp_close(fs->f,NULL);
- kfree(fs);
+ palacios_free(fs);
}
static sint64_t write_key_file(v3_keyed_stream_t stream,
struct list_head node;
};
+
//
// List of all of the user streams
//
struct palacios_user_keyed_stream_op *new;
if (!old) {
- new = kmalloc(sizeof(struct palacios_user_keyed_stream_op)+buf_len,GFP_ATOMIC);
+ new = palacios_alloc(sizeof(struct palacios_user_keyed_stream_op)+buf_len);
if (!new) {
return -1;
} else {
old->buf_len=buf_len;
return 0;
} else {
- kfree(old);
- old=0;
+ palacios_free(old);
+ *op = 0 ;
return resize_op(op,buf_len);
}
}
{
if (s->waiting) {
- printk("palacios: user keyed stream request attempted while one is already in progress on %s\n",s->url);
+ ERROR("user keyed stream request attempted while one is already in progress on %s\n",s->url);
return -1;
}
wake_up_interruptible(&(s->user_wait_queue));
// wait for someone to give us a response
- wait_event_interruptible(s->host_wait_queue, !(s->waiting));
+ while (wait_event_interruptible(s->host_wait_queue, (s->waiting == 0)) != 0) {}
// reacquire the lock for our called
spin_lock_irqsave(&(s->lock), *flags);
//
static int do_response_to_request(struct user_keyed_stream *s, unsigned long *flags)
{
+
if (!(s->waiting)) {
- printk("palacios: user keyed stream response while no request is in progress on %s\n",s->url);
+ ERROR("user keyed stream response while no request is in progress on %s\n",s->url);
return -1;
}
{
struct user_keyed_stream *s = (struct user_keyed_stream *) (filp->private_data);
unsigned long flags;
- unsigned int mask = 0;
if (!s) {
return POLLERR;
}
-
- poll_wait(filp, &(s->user_wait_queue), wait);
spin_lock_irqsave(&(s->lock), flags);
+
if (s->waiting) {
- mask |= POLLIN | POLLRDNORM;
+ spin_unlock_irqrestore(&(s->lock), flags);
+ return POLLIN | POLLRDNORM;
}
- spin_unlock_irqrestore(&(s->lock), flags);
+
+ poll_wait(filp, &(s->user_wait_queue), wait);
- return mask;
-}
+ spin_unlock_irqrestore(&(s->lock), flags);
+ return 0;
+}
-static int keyed_stream_ioctl_user(struct inode *inode, struct file *filp, unsigned int ioctl, unsigned long arg)
+static long keyed_stream_ioctl_user(struct file * filp, unsigned int ioctl, unsigned long arg)
{
void __user *argp = (void __user *)arg;
unsigned long flags;
size = sizeof(struct palacios_user_keyed_stream_op) + s->op->buf_len;
- if (copy_to_user(argp, &size, sizeof(uint64_t))) {
+ if (copy_to_user((void * __user) argp, &size, sizeof(uint64_t))) {
spin_unlock_irqrestore(&(s->lock), flags);
- printk("palacios: palacios user key size request failed to copy data\n");
+ ERROR("palacios user key size request failed to copy data\n");
return -EFAULT;
}
if (!(s->waiting)) {
spin_unlock_irqrestore(&(s->lock), flags);
- printk("palacios: palacios user key pull request when not waiting\n");
+ ERROR("palacios user key pull request when not waiting\n");
return 0;
}
size = sizeof(struct palacios_user_keyed_stream_op) + s->op->buf_len;
- if (copy_to_user(argp, s->op, size)) {
+ if (copy_to_user((void __user *) argp, s->op, size)) {
spin_unlock_irqrestore(&(s->lock), flags);
- printk("palacios: palacios user key pull request failed to copy data\n");
+ ERROR("palacios user key pull request failed to copy data\n");
return -EFAULT;
}
if (!(s->waiting)) {
spin_unlock_irqrestore(&(s->lock), flags);
- printk("palacios: palacios user key push response when not waiting\n");
+ ERROR("palacios user key push response when not waiting\n");
return 0;
}
- if (copy_from_user(&size, argp, sizeof(uint64_t))) {
- printk("palacios: palacios user key push response failed to copy size\n");
+ if (copy_from_user(&size, (void __user *) argp, sizeof(uint64_t))) {
+ ERROR("palacios user key push response failed to copy size\n");
spin_unlock_irqrestore(&(s->lock), flags);
return -EFAULT;
}
if (resize_op(&(s->op),size-sizeof(struct palacios_user_keyed_stream_op))) {
- printk("palacios: unable to resize op in user key push response\n");
+ ERROR("unable to resize op in user key push response\n");
spin_unlock_irqrestore(&(s->lock), flags);
return -EFAULT;
}
- if (copy_from_user(&(s->op), argp, size)) {
+ if (copy_from_user(s->op, (void __user *) argp, size)) {
spin_unlock_irqrestore(&(s->lock), flags);
return -EFAULT;
}
break;
default:
- printk("palacios: unknown ioctl in user keyed stream\n");
+ ERROR("unknown ioctl in user keyed stream\n");
return -EFAULT;
}
}
+
static int keyed_stream_release_user(struct inode *inode, struct file *filp)
{
struct user_keyed_stream *s = filp->private_data;
spin_lock_irqsave(&(user_streams->lock),f1);
spin_lock_irqsave(&(s->lock), f2);
- // FIXME Need to handle case of a pending request
-
list_del(&(s->node));
spin_unlock_irqrestore(&(s->lock), f2);
spin_unlock_irqrestore(&(user_streams->lock), f1);
- kfree(s->url);
- kfree(s);
+ palacios_free(s->url);
+ palacios_free(s);
return 0;
}
static struct file_operations user_keyed_stream_fops = {
.poll = keyed_stream_poll_user,
- .ioctl = keyed_stream_ioctl_user,
+ .compat_ioctl = keyed_stream_ioctl_user,
+ .unlocked_ioctl = keyed_stream_ioctl_user,
.release = keyed_stream_release_user,
};
struct user_keyed_stream *s;
if (!user_streams) {
- printk("palacios: no user space keyed streams!\n");
+ ERROR("no user space keyed streams!\n");
return -1;
}
// get the url
if (copy_from_user(&len,(void __user *)arg,sizeof(len))) {
- printk("palacios: cannot copy url len from user\n");
+ ERROR("cannot copy url len from user\n");
return -1;
}
- url = kmalloc(len,GFP_KERNEL);
+ url = palacios_alloc(len);
if (!url) {
- printk("palacios: cannot allocate url for user keyed stream\n");
+ ERROR("cannot allocate url for user keyed stream\n");
return -1;
}
if (copy_from_user(url,((void __user *)arg)+sizeof(len),len)) {
- printk("palacios: cannot copy url from user\n");
+ ERROR("cannot copy url from user\n");
return -1;
}
url[len-1]=0;
spin_lock_irqsave(&(user_streams->lock), flags);
list_for_each_entry(s, &(user_streams->streams), node) {
if (!strncasecmp(url, s->url, len)) {
- printk("palacios: user keyed stream connection with url \"%s\" already exists\n", url);
- kfree(url);
+ ERROR("user keyed stream connection with url \"%s\" already exists\n", url);
+ palacios_free(url);
return -1;
}
}
spin_unlock_irqrestore(&(user_streams->lock), flags);
// Create connection
- s = kmalloc(sizeof(struct user_keyed_stream), GFP_KERNEL);
+ s = palacios_alloc(sizeof(struct user_keyed_stream));
if (!s) {
- printk("palacios: cannot allocate new user keyed stream for %s\n",url);
- kfree(url);
+ ERROR("cannot allocate new user keyed stream for %s\n",url);
+ palacios_free(url);
return -1;
}
fd = anon_inode_getfd("v3-kstream", &user_keyed_stream_fops, s, 0);
if (fd < 0) {
- printk("palacios: cannot allocate file descriptor for new user keyed stream for %s\n",url);
- kfree(s);
- kfree(url);
+ ERROR("cannot allocate file descriptor for new user keyed stream for %s\n",url);
+ palacios_free(s);
+ palacios_free(url);
return -1;
}
struct user_keyed_stream *s;
if (!user_streams) {
- printk("palacios: no user space keyed streams available\n");
+ ERROR("no user space keyed streams available\n");
return NULL;
}
s = keyed_stream_user_find(url);
if (!s) {
- printk("palacios: cannot open user stream %s as it does not exist yet\n",url);
+ ERROR("cannot open user stream %s as it does not exist yet\n",url);
return NULL;
}
if (s->waiting) {
spin_unlock_irqrestore(&(s->lock), flags);
- printk("palacios: cannot open user stream %s as it is already in waiting state\n",url);
+ ERROR("cannot open user stream %s as it is already in waiting state\n",url);
return NULL;
}
-
s->otype = ot==V3_KS_WR_ONLY_CREATE ? V3_KS_WR_ONLY : ot;
spin_unlock_irqrestore(&(s->lock), flags);
{
unsigned long flags;
struct user_keyed_stream *s = (struct user_keyed_stream *) stream;
- struct palacios_user_keyed_stream_op *op;
uint64_t len = strlen(key)+1;
void *user_key;
spin_lock_irqsave(&(s->lock), flags);
+
if (resize_op(&(s->op),len)) {
spin_unlock_irqrestore(&(s->lock),flags);
- printk("palacios: cannot resize op in opening key %s on user keyed stream %s\n",key,s->url);
+ ERROR("cannot resize op in opening key %s on user keyed stream %s\n",key,s->url);
return NULL;
}
- op = s->op;
-
- op->type = PALACIOS_KSTREAM_OPEN_KEY;
- op->buf_len = len;
- strncpy(op->buf,key,len);
+ s->op->type = PALACIOS_KSTREAM_OPEN_KEY;
+ s->op->buf_len = len;
+ strncpy(s->op->buf,key,len);
-
// enter with it locked
if (do_request_to_response(s,&flags)) {
spin_unlock_irqrestore(&(s->lock),flags);
- printk("palacios: request/response handling failed\n");
+ ERROR("request/response handling failed\n");
return NULL;
}
// return with it locked
user_key=s->op->user_key;
spin_unlock_irqrestore(&(s->lock),flags);
-
+
return user_key;
}
static void close_key_user(v3_keyed_stream_t stream, v3_keyed_stream_key_t key)
{
struct user_keyed_stream *s = (struct user_keyed_stream *) stream;
- struct palacios_user_keyed_stream_op *op;
uint64_t len = 0;
unsigned long flags;
if (resize_op(&(s->op),len)) {
spin_unlock_irqrestore(&(s->lock),flags);
- printk("palacios: cannot resize op in closing key 0x%p on user keyed stream %s\n",key,s->url);
+ ERROR("cannot resize op in closing key 0x%p on user keyed stream %s\n",key,s->url);
return;
}
- op = s->op;
-
- op->type = PALACIOS_KSTREAM_CLOSE_KEY;
- op->buf_len = len;
- op->user_key = key;
+ s->op->type = PALACIOS_KSTREAM_CLOSE_KEY;
+ s->op->buf_len = len;
+ s->op->user_key = key;
// enter with it locked
if (do_request_to_response(s,&flags)) {
spin_unlock_irqrestore(&(s->lock),flags);
- printk("palacios: request/response handling failed\n");
+ ERROR("request/response handling failed\n");
return;
}
// return with it locked
spin_unlock_irqrestore(&(s->lock),flags);
-
+
return;
}
{
struct user_keyed_stream *s = (struct user_keyed_stream *) stream;
- struct palacios_user_keyed_stream_op *op;
uint64_t len = 0 ;
sint64_t xfer;
unsigned long flags;
if (s->otype != V3_KS_RD_ONLY) {
spin_unlock_irqrestore(&(s->lock),flags);
- printk("palacios: attempt to read key from stream that is not in read state on %s\n",s->url);
+ ERROR("attempt to read key from stream that is not in read state on %s\n",s->url);
}
if (resize_op(&(s->op),len)) {
spin_unlock_irqrestore(&(s->lock),flags);
- printk("palacios: cannot resize op in reading key 0x%p on user keyed stream %s\n",key,s->url);
+ ERROR("cannot resize op in reading key 0x%p on user keyed stream %s\n",key,s->url);
return -1;
}
- op = s->op;
-
- op->type = PALACIOS_KSTREAM_READ_KEY;
- op->buf_len = len;
- op->user_key = key;
+ s->op->type = PALACIOS_KSTREAM_READ_KEY;
+ s->op->buf_len = len ;
+ s->op->xfer = rlen;
+ s->op->user_key = key;
// enter with it locked
if (do_request_to_response(s,&flags)) {
spin_unlock_irqrestore(&(s->lock),flags);
- printk("palacios: request/response handling failed\n");
+ ERROR("request/response handling failed\n");
return -1;
}
// return with it locked
- if (op->xfer>0) {
- memcpy(buf,op->buf,op->xfer);
+
+ if (s->op->xfer>0) {
+ memcpy(buf,s->op->buf,s->op->xfer);
}
- xfer=op->xfer;
+ xfer=s->op->xfer;
spin_unlock_irqrestore(&(s->lock),flags);
if (s->otype != V3_KS_WR_ONLY) {
spin_unlock_irqrestore(&(s->lock),flags);
- printk("palacios: attempt to write key on stream that is not in write state on %s\n",s->url);
+ ERROR("attempt to write key on stream that is not in write state on %s\n",s->url);
}
if (resize_op(&(s->op),len)) {
spin_unlock_irqrestore(&(s->lock),flags);
- printk("palacios: cannot resize op in reading key 0x%p on user keyed stream %s\n",key,s->url);
+ ERROR("cannot resize op in reading key 0x%p on user keyed stream %s\n",key,s->url);
return -1;
}
op = s->op;
- op->type = PALACIOS_KSTREAM_WRITE_KEY;
- op->buf_len = len;
- op->user_key = key;
+ s->op->type = PALACIOS_KSTREAM_WRITE_KEY;
+ s->op->buf_len = len;
+ s->op->xfer = wlen;
+ s->op->user_key = key;
- memcpy(op->buf,buf,wlen);
+ memcpy(s->op->buf,buf,wlen);
// enter with it locked
if (do_request_to_response(s,&flags)) {
spin_unlock_irqrestore(&(s->lock),flags);
- printk("palacios: request/response handling failed\n");
+ ERROR("request/response handling failed\n");
return -1;
}
// return with it locked
- xfer=op->xfer;
+ xfer=s->op->xfer;
spin_unlock_irqrestore(&(s->lock),flags);
+/****************************************************************************************
+ * Network-based implementation ("net:")
+ *****************************************************************************************/
+
+
+#define NET_MAX_KEY_LEN 128
+
+struct net_keyed_stream {
+ int stype;
+ int ot;
+ struct net_stream * ns;
+};
+
+struct net_stream {
+ int stype;
+ struct socket *sock;
+};
+
+
+//ignore the arguments given here currently
+static struct net_stream * create_net_stream(void)
+{
+ struct net_stream * ns = NULL;
+
+ ns = palacios_alloc(sizeof(struct net_stream));
+
+ if (!ns) {
+ ERROR("Cannot allocate a net_stream\n");
+ return 0;
+ }
+
+ memset(ns, 0, sizeof(struct net_stream));
+
+ ns->stype = STREAM_NETWORK;
+
+ return ns;
+}
+
+static void close_socket(v3_keyed_stream_t stream)
+{
+ struct net_keyed_stream *nks = (struct net_keyed_stream *) stream;
+
+ if (nks) {
+ struct net_stream *ns = nks->ns;
+
+ if (ns) {
+ ns->sock->ops->release(ns->sock);
+ palacios_free(ns);
+ ERROR("Close Socket\n");
+ }
+
+ palacios_free(ns);
+ }
+}
+
+
+static void close_stream_net(v3_keyed_stream_t stream)
+{
+ close_socket(stream);
+}
+
+static int connect_to_ip(struct net_stream *ns, int hostip, int port)
+{
+ struct sockaddr_in client;
+
+ if (ns == NULL) {
+ return -1;
+ }
+
+ if (sock_create(PF_INET,SOCK_STREAM,IPPROTO_TCP,&(ns->sock))<0) {
+ ERROR("Cannot create accept socket\n");
+ return -1;
+ }
+
+
+ client.sin_family = AF_INET;
+ client.sin_port = htons(port);
+ client.sin_addr.s_addr = hostip;//in_aton(hostip);
+
+ return ns->sock->ops->connect(ns->sock, (struct sockaddr *)&client, sizeof(client), 0);
+}
+
+static int send_msg(struct net_stream *ns, char * buf, int len)
+{
+ int left=len;
+
+ if (!ns) {
+ ERROR("Send message on null net_stream\n");
+ return -1;
+ }
+
+ if (!(ns->sock)) {
+ ERROR("Send message on net_stream without socket\n");
+ return -1;
+ }
+
+ while (left>0) {
+
+ struct msghdr msg;
+ mm_segment_t oldfs;
+ struct iovec iov;
+ int err = 0;
+
+
+ msg.msg_flags = MSG_NOSIGNAL;//MSG_DONTWAIT;
+ msg.msg_name = 0;
+ msg.msg_namelen = 0;
+ msg.msg_control = NULL;
+ msg.msg_controllen = 0;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+ iov.iov_base = (char *)&(buf[len-left]);
+ iov.iov_len = (size_t)left;
+
+ oldfs = get_fs();
+ set_fs(KERNEL_DS);
+
+ err = sock_sendmsg(ns->sock, &msg, (size_t)left);
+
+ set_fs(oldfs);
+
+ if (err<0) {
+ ERROR("Send msg error %d\n",err);
+ return err;
+ } else {
+ left-=len;
+ }
+ }
+
+ return len;
+}
+
+
+
+static int recv_msg(struct net_stream *ns, char * buf, int len)
+{
+
+ int left=len;
+
+ if (!ns) {
+ ERROR("Receive message on null net_stream\n");
+ return -1;
+ }
+
+ if (!(ns->sock)) {
+ ERROR("Receive message on net_stream without socket\n");
+ return -1;
+ }
+
+
+ while (left>0) {
+
+ struct msghdr msg;
+ mm_segment_t oldfs;
+ struct iovec iov;
+ int err;
+
+ msg.msg_flags = 0;
+ msg.msg_name = 0;
+ msg.msg_namelen = 0;
+ msg.msg_control = NULL;
+ msg.msg_controllen = 0;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+ iov.iov_base = (void *)&(buf[len-left]);
+ iov.iov_len = (size_t)left;
+
+ oldfs = get_fs();
+ set_fs(KERNEL_DS);
+
+ err = sock_recvmsg(ns->sock, &msg, (size_t)left, 0);
+
+ set_fs(oldfs);
+
+ if (err<0) {
+ return err;
+ } else {
+ left -= err;
+ }
+ }
+ return len;
+}
+
+static struct net_stream * accept_once(struct net_stream * ns, const int port)
+{
+ struct socket *accept_sock;
+ struct sockaddr_in addr;
+ int err;
+
+ if (!ns) {
+ ERROR("Accept called on null net_stream\n");
+ return 0;
+ }
+
+ if (sock_create(PF_INET,SOCK_STREAM,IPPROTO_TCP,&accept_sock)<0) {
+ ERROR("Cannot create accept socket\n");
+ return NULL;
+ }
+
+
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(port);
+ addr.sin_addr.s_addr = INADDR_ANY;
+
+ err = accept_sock->ops->bind(accept_sock, (struct sockaddr *)&addr, sizeof(addr));
+
+ if (err<0) {
+ ERROR("Bind err: %d\n",err);
+ return NULL;
+ }
+
+ err = accept_sock->ops->listen(accept_sock,2);
+
+ if (err<0) {
+ ERROR("Listen err: %d\n",err);
+ return NULL;
+ }
+
+ // Init the socket in the network strream
+
+ if (sock_create(PF_INET,SOCK_STREAM,IPPROTO_TCP,&(ns->sock))<0) {
+ ERROR("Cannot create socket\n");
+ return NULL;
+ }
+
+
+ // Do the actual accept
+
+ if (accept_sock->ops->accept(accept_sock,ns->sock,0)<0) {
+ ERROR("accept failed");
+ return NULL;
+ }
+
+ // close the accept socket
+ accept_sock->ops->release(accept_sock);
+ palacios_free(accept_sock);
+
+ return ns;
+}
+
+
+static struct v3_keyed_stream_t * open_stream_net(char * url,v3_keyed_stream_open_t ot)
+{
+ struct net_keyed_stream * nks;
+ int url_len;
+ int i;
+ int delimit[3];
+ int k;
+ char mode;
+ int ip_len;
+ int port_len;
+
+ nks = palacios_alloc(sizeof(struct net_keyed_stream));
+
+ if (!nks) {
+ ERROR("Could not allocate space in open_stream_net\n");
+ return 0;
+ }
+
+ nks->ot = ot == V3_KS_WR_ONLY_CREATE ? V3_KS_WR_ONLY : ot;
+
+ nks->stype = STREAM_NETWORK;
+
+ nks->ns = create_net_stream();
+
+ if (!(nks->ns)) {
+ ERROR("Could not create network stream\n");
+ palacios_free(nks);
+ return 0;
+ }
+
+ url_len=strlen(url);
+ k=0;
+
+
+ for(i = 0; i < url_len;i++){
+ if(url[i] == ':'){
+ delimit[k] = i;
+ k++;
+ }
+ }
+
+ mode = url[delimit[0] + 1];
+ ip_len = delimit[2] - delimit[1];
+ port_len = url_len - delimit[2];
+
+
+ {
+ char ip[ip_len];
+ char port[port_len];
+ int host_ip;
+ int host_port;
+
+
+ strncpy(ip,url + delimit[1]+1,ip_len-1);
+ ip[ip_len-1]='\0';
+
+ host_ip = in_aton(ip);
+
+ strncpy(port,url+ delimit[2]+1,port_len-1);
+ port[port_len-1]='\0';
+
+ host_port = simple_strtol(port,NULL,10);
+
+ INFO("ip is %s\n",ip);
+ INFO("host_ip is %x\n", host_ip);
+ INFO("port is %s (%d)\n",port,host_port);
+
+ if (mode == 'a'){
+ // accept a request
+ INFO("Accepting Connection on INADDR_ANY port:%d\n",host_port);
+ nks->ns = accept_once(nks->ns, host_port);
+ } else if (mode == 'c'){
+ // call connect to ip
+ INFO("Connecting to %s:%d\n",ip,host_port);
+ connect_to_ip(nks->ns,host_ip, host_port);
+ } else {
+ ERROR("Mode not recognized\n");
+ palacios_free(nks);
+ return NULL;
+ }
+
+ return (v3_keyed_stream_t)nks;
+ }
+}
+
+static void preallocate_hint_key_net(v3_keyed_stream_t stream, char *key,uint64_t size)
+{
+ //do nothing
+}
+
+static v3_keyed_stream_key_t open_key_net(v3_keyed_stream_t stream,char *key)
+{
+ struct net_keyed_stream * nks = (struct net_keyed_stream *)stream;
+
+ // reciever of the key name
+ if (nks->ot==V3_KS_WR_ONLY)
+ {
+ unsigned short keylen = strlen(key);
+
+ if (keylen>NET_MAX_KEY_LEN || keylen>=32768) {
+ ERROR("Key is too long\n");
+ return NULL;
+ }
+
+ {
+ // on-stack allocation here demands that we
+ // keep key length low...
+ char msg[keylen+3];
+ int next = 0;
+
+ // Opening a key for writing sends a notice of the
+ // key length and the key name on the channel
+
+ msg[next++]=keylen & 0xFF;
+ msg[next]=(keylen>>8) & 0xFF;
+ // Set flag bit
+ msg[next]=msg[next] | 0x80; // 0x80 is 128 and OR will flip leading bit to 1
+
+ strncpy(msg+2,key,keylen); // will also copy trailing zero
+
+ if (send_msg(nks->ns,msg,keylen+2) != keylen+2) {
+ ERROR("Unable to open key for writing on net_stream (send key len+name)\n");
+ return NULL;
+ }
+ }
+ }
+
+ if (nks->ot==V3_KS_RD_ONLY) {
+ char msg_info[2];
+ int next = 0;
+ int keylen = 0;
+
+ if (recv_msg(nks->ns,msg_info,2) != 2) {
+ ERROR("Unable to open key for reading on net_stream (recv key len)\n");
+ return NULL;
+ }
+
+ next = 0;
+ keylen = 0;
+
+ keylen |= msg_info[next++];
+
+ if ((msg_info[next] & 0x80) != 0x80) {
+ ERROR("Flag bit not set on receive of key length\n");
+ return NULL;
+ } else {
+ msg_info[next] &= 0x7F; // flip the msb back to zero (clear flag)
+ }
+
+ keylen |= msg_info[next]<<8;
+
+ if (keylen > NET_MAX_KEY_LEN) {
+ ERROR("Received key length is too big\n");
+ return NULL;
+ }
+
+ {
+
+ char msg[keylen+1];
+
+ if (recv_msg(nks->ns,msg,keylen) != keylen) {
+ ERROR("Unable to receive key\n");
+ return NULL;
+ }
+ msg[keylen]=0;
+
+ if (strncmp(key,msg,keylen)!=0) {
+ ERROR("Key mismatch in open_key_net - expect %s but got %s\n",key,msg);
+ return NULL;
+ }
+ }
+ }
+
+ return (v3_keyed_stream_key_t)key;
+}
+
+static void close_key_net(v3_keyed_stream_t stream, v3_keyed_stream_key_t input_key)
+{
+ char * key = (char*)input_key;
+ struct net_keyed_stream * nks = (struct net_keyed_stream *)stream;
+
+
+ if (nks->ot==V3_KS_WR_ONLY) {
+ unsigned short keylen = strlen(key);
+
+ if (keylen > NET_MAX_KEY_LEN || keylen>=32768) {
+ ERROR("Key length too long in close_key_net\n");
+ return;
+ }
+
+ {
+ char msg[keylen+3];
+ int next = 0;
+
+ msg[next++]=keylen & 0xFF;
+ msg[next]=(keylen>>8) & 0xFF;
+ // flag
+ msg[next]=msg[next] | 0x80; // 0x80 is 128 and OR will filp leading bit to 1
+ strncpy(msg+2,key,keylen); // will copy the zero
+ msg[keylen+2]=0;
+ if (send_msg(nks->ns,msg,keylen+2)!=keylen+2) {
+ ERROR("Cannot send key on close_key_net\n");
+ return;
+ }
+ }
+ }
+
+ if (nks->ot==V3_KS_RD_ONLY) {
+ char msg_info[2];
+ int next;
+ int keylen;
+
+ if (recv_msg(nks->ns,msg_info,2) != 2) {
+ ERROR("Cannot recv key length on close_key_net\n");
+ return;
+ }
+
+ next = 0;
+ keylen = 0;
+
+ keylen |= msg_info[next++];
+
+ if ((msg_info[next] & 0x80) != 0x80) {
+ ERROR("Missing flag in close_key_net receive\n");
+ return;
+ }
+
+ msg_info[next] &= 0x7F; // flip the msb back to zero
+
+ keylen |= msg_info[next]<<8;
+
+ {
+ char msg[keylen+1];
+
+ if (recv_msg(nks->ns,msg,keylen)!=keylen) {
+ ERROR("Did not receive all of key in close_key_net receive\n");
+ return;
+ }
+
+ msg[keylen]=0;
+
+ if (strncmp(key,msg,keylen)!=0) {
+ ERROR("Key mismatch in close_key_net - expect %s but got %s\n",key,msg);
+ return;
+ }
+ }
+ }
+}
+
+static sint64_t write_key_net(v3_keyed_stream_t stream, v3_keyed_stream_key_t key, void *buf, sint64_t len)
+{
+ struct net_keyed_stream * nks = (struct net_keyed_stream *)stream;
+
+ if (!buf) {
+ ERROR("Buf is NULL in write_key_net\n");
+ return -1;
+ }
+
+ if (len<0) {
+ ERROR("len is negative in write_key_net\n");
+ return -1;
+ }
+
+ if (!key){
+ ERROR("write_key: key is NULL in write_key_net\n");
+ return -1;
+ }
+
+
+ if (!nks) {
+ ERROR("nks is NULL in write_key_net\n");
+ return -1;
+ }
+
+ if (nks->ot==V3_KS_WR_ONLY) {
+ if (send_msg(nks->ns,(char*)(&len),sizeof(len))!=sizeof(len)) {
+ ERROR("Could not send data length in write_key_net\n");
+ return -1;
+ }
+ if (send_msg(nks->ns,buf,len)!=len) {
+ ERROR("Could not send data in write_key_net\n");
+ return -1;
+ }
+ } else {
+ ERROR("Permission not correct in write_key_net\n");
+ return -1;
+ }
+
+ return len;
+}
+
+
+static sint64_t read_key_net(v3_keyed_stream_t stream, v3_keyed_stream_key_t key, void *buf, sint64_t len)
+{
+ struct net_keyed_stream * nks = (struct net_keyed_stream *)stream;
+
+ if (!buf) {
+ ERROR("Buf is NULL in read_key_net\n");
+ return -1;
+ }
+
+ if(len<0) {
+ ERROR("len is negative in read_key_net\n");
+ return -1;
+ }
+
+ if (!key) {
+ ERROR("read_key: key is NULL in read_key_net\n");
+ return -1;
+ }
+
+
+ if (nks->ot==V3_KS_RD_ONLY) {
+
+ sint64_t slen;
+
+ if (recv_msg(nks->ns,(char*)(&slen),sizeof(slen))!=sizeof(slen)) {
+ ERROR("Cannot receive data len in read_key_net\n");
+ return -1;
+ }
+
+ if (slen!=len) {
+ ERROR("Data len expected does not matched data len decoded in read_key_net\n");
+ return -1;
+ }
+
+ if (recv_msg(nks->ns,buf,len)!=len) {
+ ERROR("Cannot recieve data in read_key_net\n");
+ return -1;
+ }
+
+ } else {
+ ERROR("Permissions incorrect for the stream in read_key_net\n");
+ return -1;
+ }
+
+ return len;
+
+}
+
/***************************************************************************************************
Generic interface
return open_stream_file(url,ot);
} else if (!strncasecmp(url,"user:",5)) {
return open_stream_user(url,ot);
+ } else if(!strncasecmp(url,"net:",4)){
+ return open_stream_net(url,ot);
} else {
- printk("palacios: unsupported type in attempt to open keyed stream \"%s\"\n",url);
+ ERROR("unsupported type in attempt to open keyed stream \"%s\"\n",url);
return 0;
}
}
case STREAM_USER:
return close_stream_user(stream);
break;
+ case STREAM_NETWORK:
+ return close_stream_net(stream);
+ break;
default:
- printk("palacios: unknown stream type %d in close\n",gks->stype);
+ ERROR("unknown stream type %d in close\n",gks->stype);
break;
}
}
case STREAM_USER:
return preallocate_hint_key_user(stream,key,size);
break;
+ case STREAM_NETWORK:
+ return preallocate_hint_key_net(stream,key,size);
+ break;
default:
- printk("palacios: unknown stream type %d in preallocate_hint_key\n",gks->stype);
+ ERROR("unknown stream type %d in preallocate_hint_key\n",gks->stype);
break;
}
return;
case STREAM_USER:
return open_key_user(stream,key);
break;
+ case STREAM_NETWORK:
+ return open_key_net(stream, key);
+ break;
default:
- printk("palacios: unknown stream type %d in open_key\n",gks->stype);
+ ERROR("unknown stream type %d in open_key\n",gks->stype);
break;
}
return 0;
case STREAM_USER:
return close_key_user(stream,key);
break;
+ case STREAM_NETWORK:
+ return close_key_net(stream, key);
+ break;
default:
- printk("palacios: unknown stream type %d in close_key\n",gks->stype);
+ ERROR("unknown stream type %d in close_key\n",gks->stype);
break;
}
// nothing to do
case STREAM_USER:
return write_key_user(stream,key,buf,len);
break;
+ case STREAM_NETWORK:
+ return write_key_net(stream,key,buf,len);
+ break;
default:
- printk("palacios: unknown stream type %d in write_key\n",gks->stype);
+ ERROR("unknown stream type %d in write_key\n",gks->stype);
return -1;
break;
}
case STREAM_USER:
return read_key_user(stream,key,buf,len);
break;
+ case STREAM_NETWORK:
+ return read_key_net(stream,key,buf,len);
+ break;
default:
- printk("palacios: unknown stream type %d in read_key\n",gks->stype);
+ ERROR("unknown stream type %d in read_key\n",gks->stype);
return -1;
break;
}
mem_streams = palacios_create_htable(DEF_NUM_STREAMS,hash_func,hash_comp);
if (!mem_streams) {
- printk("palacios: failed to allocated stream pool for in-memory streams\n");
+ ERROR("failed to allocated stream pool for in-memory streams\n");
return -1;
}
- user_streams = kmalloc(sizeof(struct user_keyed_streams),GFP_KERNEL);
+ user_streams = palacios_alloc(sizeof(struct user_keyed_streams));
if (!user_streams) {
- printk("palacios: failed to allocated list for user streams\n");
+ ERROR("failed to allocated list for user streams\n");
return -1;
}
{
palacios_free_htable(mem_streams,1,1);
- kfree(user_streams);
+ palacios_free(user_streams);
- printk("Deinit of Palacios Keyed Streams likely leaked memory\n");
+ WARNING("Deinit of Palacios Keyed Streams likely leaked memory\n");
return 0;
}