2 * Palacios keyed stream interface
4 * Plus implementations for mem, file, and user space implementations
6 * (c) Peter Dinda, 2011 (interface, mem + file implementations + recooked user impl)
7 * (c) Clint Sbisa, 2011 (initial user space implementation on which this is based)
11 #include <linux/file.h>
12 #include <linux/uaccess.h>
13 #include <linux/namei.h>
14 #include <linux/vmalloc.h>
15 #include <linux/poll.h>
16 #include <linux/anon_inodes.h>
19 #include "util-hashtable.h"
20 #include "linux-exts.h"
23 #define sint64_t int64_t
24 #include <interfaces/vmm_keyed_stream.h>
26 #include "iface-keyed-stream-user.h"
29 This is an implementation of the Palacios keyed stream interface
30 that supports three flavors of streams:
32 "mem:" Streams are stored in a hash table
33 The values for this hash table are hash tables associated with
36 "file:" Streams are stored in files. Each high-level
37 open corresponds to a directory, while key corresponds to
38 a distinct file in that directory.
40 "user:" Stream requests are bounced to user space to be
41 handled there. A rendezvous approach similar to the host
42 device userland support is used
46 #define STREAM_GENERIC 0
52 All keyed streams and streams indicate their implementation type within the first field
54 struct generic_keyed_stream {
58 struct generic_stream {
65 /****************************************************************************************
66 Memory-based implementation ("mem:")
67 ****************************************************************************************/
69 #define DEF_NUM_STREAMS 16
70 #define DEF_NUM_KEYS 128
74 A memory keyed stream is a pointer to the underlying hash table
75 while a memory stream contains an extensible buffer for the stream
77 struct mem_keyed_stream {
79 v3_keyed_stream_open_t ot;
91 static struct mem_stream *create_mem_stream_internal(uint64_t size)
93 struct mem_stream *m = kmalloc(sizeof(struct mem_stream),GFP_KERNEL);
100 m->data = vmalloc(size);
107 m->stype = STREAM_MEM;
116 static struct mem_stream *create_mem_stream(void)
118 return create_mem_stream_internal(DEF_SIZE);
121 static void destroy_mem_stream(struct mem_stream *m)
132 static int expand_mem_stream(struct mem_stream *m, uint32_t new_size)
134 void *data = vmalloc(new_size);
141 nc = (new_size<m->data_max) ? new_size : m->data_max;
143 memcpy(data,m->data,nc);
149 if (m->size<m->data_max) {
156 static uint32_t write_mem_stream(struct mem_stream *m,
160 if ((m->ptr + len) > m->size) {
161 if (expand_mem_stream(m,m->ptr + len)) {
165 memcpy(m->data+m->ptr,data,len);
173 static uint32_t read_mem_stream(struct mem_stream *m,
177 if ((m->ptr + len) > m->data_max) {
180 memcpy(data,m->data+m->ptr,len);
188 static void reset_mem_stream(struct mem_stream *m)
194 static inline uint_t hash_func(addr_t key)
196 return palacios_hash_buffer((uchar_t*)key,strlen((uchar_t*)key));
199 static inline int hash_comp(addr_t k1, addr_t k2)
201 return strcasecmp((char*)k1,(char*)k2)==0;
205 // This stores all the memory keyed streams streams
206 static struct hashtable *mem_streams=0;
209 static v3_keyed_stream_t open_stream_mem(char *url,
210 v3_keyed_stream_open_t ot)
213 if (strncasecmp(url,"mem:",4)) {
214 printk("palacios: illegitimate attempt to open memory stream \"%s\"\n",url);
220 case V3_KS_WR_ONLY: {
221 struct mem_keyed_stream *mks = (struct mem_keyed_stream *) palacios_htable_search(mem_streams,(addr_t)(url+4));
225 return (v3_keyed_stream_t) mks;
229 case V3_KS_WR_ONLY_CREATE: {
230 struct mem_keyed_stream *mks = (struct mem_keyed_stream *) palacios_htable_search(mem_streams,(addr_t)(url+4));
234 mykey = kmalloc(strlen(url+4)+1,GFP_KERNEL);
237 printk("palacios: cannot allocate space for new in-memory keyed stream %s\n",url);
243 mks = (struct mem_keyed_stream *) kmalloc(sizeof(struct mem_keyed_stream),GFP_KERNEL);
247 printk("palacios: cannot allocate in-memory keyed stream %s\n",url);
251 mks->ht = (void*) palacios_create_htable(DEF_NUM_KEYS,hash_func,hash_comp);
255 printk("palacios: cannot allocate in-memory keyed stream %s\n",url);
260 if (!palacios_htable_insert(mem_streams,(addr_t)(mykey),(addr_t)mks)) {
261 palacios_free_htable(mks->ht,1,1);
264 printk("palacios: cannot insert in-memory keyed stream %s\n",url);
267 mks->stype=STREAM_MEM;
270 mks->ot=V3_KS_WR_ONLY;
278 printk("palacios: unsupported open type in open_stream_mem\n");
288 static void close_stream_mem(v3_keyed_stream_t stream)
295 static v3_keyed_stream_key_t open_key_mem(v3_keyed_stream_t stream,
298 struct mem_keyed_stream *mks = (struct mem_keyed_stream *) stream;
299 struct hashtable *s = mks->ht;
301 struct mem_stream *m;
303 m = (struct mem_stream *) palacios_htable_search(s,(addr_t)key);
306 char *mykey = kmalloc(strlen(key)+1,GFP_KERNEL);
309 printk("palacios: cannot allocate copy of key for key %s\n",key);
315 m = create_mem_stream();
319 printk("palacios: cannot allocate mem keyed stream for key %s\n",key);
323 if (!palacios_htable_insert(s,(addr_t)mykey,(addr_t)m)) {
324 destroy_mem_stream(m);
326 printk("palacios: cannot insert mem keyed stream for key %s\n",key);
337 static void preallocate_hint_key_mem(v3_keyed_stream_t stream,
341 struct mem_keyed_stream *mks = (struct mem_keyed_stream *) stream;
342 struct hashtable *s = mks->ht;
344 struct mem_stream *m;
346 if (mks->ot != V3_KS_WR_ONLY) {
350 m = (struct mem_stream *) palacios_htable_search(s,(addr_t)key);
355 mykey=kmalloc(strlen(key)+1,GFP_KERNEL);
358 printk("palacios: cannot allocate key spce for preallocte for key %s\n",key);
364 m = create_mem_stream_internal(size);
367 printk("palacios: cannot preallocate mem keyed stream for key %s\n",key);
371 if (!palacios_htable_insert(s,(addr_t)mykey,(addr_t)m)) {
372 printk("palacios: cannot insert preallocated mem keyed stream for key %s\n",key);
373 destroy_mem_stream(m);
377 if (m->data_max < size) {
378 if (expand_mem_stream(m,size)) {
379 printk("palacios: cannot expand key for preallocation for key %s\n",key);
389 static void close_key_mem(v3_keyed_stream_t stream,
390 v3_keyed_stream_key_t key)
396 static sint64_t write_key_mem(v3_keyed_stream_t stream,
397 v3_keyed_stream_key_t key,
401 struct mem_keyed_stream *mks = (struct mem_keyed_stream *) stream;
402 struct mem_stream *m = (struct mem_stream *) key;
406 if (mks->ot!=V3_KS_WR_ONLY) {
414 mylen = (uint32_t) len;
416 writelen=write_mem_stream(m,buf,mylen);
418 if (writelen!=mylen) {
419 printk("palacios: failed to write all data for key\n");
422 return (sint64_t)writelen;
426 static sint64_t read_key_mem(v3_keyed_stream_t stream,
427 v3_keyed_stream_key_t key,
431 struct mem_keyed_stream *mks = (struct mem_keyed_stream *) stream;
432 struct mem_stream *m = (struct mem_stream *) key;
436 if (mks->ot!=V3_KS_RD_ONLY) {
444 mylen = (uint32_t) len;
446 readlen=read_mem_stream(m,buf,mylen);
448 if (readlen!=mylen) {
449 printk("palacios: failed to read all data for key\n");
452 return (sint64_t)readlen;
457 /***************************************************************************************************
458 File-based implementation ("file:")
459 *************************************************************************************************/
462 A file keyed stream contains the fd of the directory
466 struct file_keyed_stream {
468 v3_keyed_stream_open_t ot;
474 struct file *f; // the opened file
478 static v3_keyed_stream_t open_stream_file(char *url,
479 v3_keyed_stream_open_t ot)
481 struct file_keyed_stream *fks;
484 if (strncasecmp(url,"file:",5)) {
485 printk("palacios: illegitimate attempt to open file stream \"%s\"\n",url);
489 fks = kmalloc(sizeof(struct file_keyed_stream),GFP_KERNEL);
492 printk("palacios: cannot allocate space for file stream\n");
496 fks->path = (char*)kmalloc(strlen(url+5)+1,GFP_KERNEL);
499 printk("palacios: cannot allocate space for file stream\n");
504 strcpy(fks->path,url+5);
506 fks->stype=STREAM_FILE;
508 fks->ot= ot==V3_KS_WR_ONLY_CREATE ? V3_KS_WR_ONLY : ot;
510 // Does the directory exist, and can we read/write it?
512 if (path_lookup(fks->path,LOOKUP_DIRECTORY|LOOKUP_FOLLOW,&nd)) {
514 // directory does does not exist.
516 if (ot==V3_KS_RD_ONLY || ot==V3_KS_WR_ONLY) {
518 // we are not being asked to create it
519 printk("palacios: attempt to open %s, which does not exist\n",fks->path);
524 // We are being asked to create it
530 if (path_lookup(fks->path,LOOKUP_PARENT|LOOKUP_FOLLOW,&nd)) {
531 printk("palacios: attempt to create %s failed because its parent cannot be looked up\n",fks->path);
535 // Can we write to the parent?
537 if (inode_permission(nd.path.dentry->d_inode, MAY_WRITE | MAY_EXEC)) {
538 printk("palacios: attempt to open %s, which has the wrong permissions for directory creation\n",fks->path);
542 // OK, we can, so let's create it
544 de = lookup_create(&nd,1);
547 printk("palacios: cannot allocate dentry\n");
551 err = vfs_mkdir(nd.path.dentry->d_inode, de, 0700);
553 // lookup_create locks this for us!
555 mutex_unlock(&(nd.path.dentry->d_inode->i_mutex));
558 printk("palacios: attempt to create %s failed because mkdir failed\n",fks->path);
562 // now the directory should exist and have reasonable permissions
563 return (v3_keyed_stream_t) fks;
568 // we must be in V3_KS_RD_ONLY or V3_KS_WR_ONLY,
569 // and the directory exists, so we must check the permissions
571 if (inode_permission(nd.path.dentry->d_inode, MAY_EXEC | (ot==V3_KS_RD_ONLY ? MAY_READ : MAY_WRITE))) {
572 printk("palacios: attempt to open %s, which has the wrong permissions\n",fks->path);
575 return (v3_keyed_stream_t) fks;
586 static void close_stream_file(v3_keyed_stream_t stream)
588 struct file_keyed_stream *fks = (struct file_keyed_stream *) stream;
595 static void preallocate_hint_key_file(v3_keyed_stream_t stream,
602 static v3_keyed_stream_key_t open_key_file(v3_keyed_stream_t stream,
605 struct file_keyed_stream *fks = (struct file_keyed_stream *) stream;
606 struct file_stream *fs;
609 // the path is the stream's path plus the key name
610 // file:/home/foo + "regext" => "/home/foo/regext"
611 path = (char *) kmalloc(strlen(fks->path)+strlen(key)+2,GFP_KERNEL);
613 printk("palacios: cannot allocate file keyed stream for key %s\n",key);
616 strcpy(path,fks->path);
620 fs = (struct file_stream *) kmalloc(sizeof(struct file_stream *),GFP_KERNEL);
623 printk("palacios: cannot allocate file keyed stream for key %s\n",key);
628 fs->stype=STREAM_FILE;
630 fs->f = filp_open(path,O_RDWR|O_CREAT,0600);
633 printk("palacios: cannot open relevent file \"%s\" for stream \"file:%s\" and key \"%s\"\n",path,fks->path,key);
645 static void close_key_file(v3_keyed_stream_t stream,
646 v3_keyed_stream_key_t key)
648 struct file_stream *fs = (struct file_stream *) key;
650 filp_close(fs->f,NULL);
655 static sint64_t write_key_file(v3_keyed_stream_t stream,
656 v3_keyed_stream_key_t key,
660 struct file_keyed_stream *fks = (struct file_keyed_stream *) stream;
661 struct file_stream *fs = (struct file_stream *) key;
663 ssize_t done, left, total;
665 if (fks->ot!=V3_KS_WR_ONLY) {
680 done = fs->f->f_op->write(fs->f, buf+(total-left), left, &(fs->f->f_pos));
694 static sint64_t read_key_file(v3_keyed_stream_t stream,
695 v3_keyed_stream_key_t key,
699 struct file_keyed_stream *fks = (struct file_keyed_stream *) stream;
700 struct file_stream *fs = (struct file_stream *) key;
702 ssize_t done, left, total;
704 if (fks->ot!=V3_KS_RD_ONLY) {
719 done = fs->f->f_op->read(fs->f, buf+(total-left), left, &(fs->f->f_pos));
735 /***************************************************************************************************
736 User implementation ("user:")
737 *************************************************************************************************/
740 // List of all user keyed stream connections for the guest
741 struct user_keyed_streams {
743 struct list_head streams;
747 // A single keyed stream connection to user space
748 struct user_keyed_stream {
750 v3_keyed_stream_open_t otype;
756 wait_queue_head_t user_wait_queue;
757 wait_queue_head_t host_wait_queue;
759 struct palacios_user_keyed_stream_op *op;
761 struct list_head node;
766 // List of all of the user streams
768 static struct user_keyed_streams *user_streams;
772 static int resize_op(struct palacios_user_keyed_stream_op **op, uint64_t buf_len)
774 struct palacios_user_keyed_stream_op *old = *op;
775 struct palacios_user_keyed_stream_op *new;
778 new = kmalloc(sizeof(struct palacios_user_keyed_stream_op)+buf_len,GFP_ATOMIC);
782 new->len=sizeof(struct palacios_user_keyed_stream_op)+buf_len;
783 new->buf_len=buf_len;
788 if ((old->len-sizeof(struct palacios_user_keyed_stream_op)) >= buf_len) {
789 old->buf_len=buf_len;
794 return resize_op(op,buf_len);
800 // The assumption is that we enter this with the stream locked
801 // and we will return with it locked; additionally, the op structure
802 // will be overwritten with the response
804 static int do_request_to_response(struct user_keyed_stream *s, unsigned long *flags)
808 printk("palacios: user keyed stream request attempted while one is already in progress on %s\n",s->url);
812 // we are now waiting for a response
815 // release the stream
816 spin_unlock_irqrestore(&(s->lock), *flags);
818 // wake up anyone waiting on it
819 wake_up_interruptible(&(s->user_wait_queue));
821 // wait for someone to give us a response
822 while (wait_event_interruptible(s->host_wait_queue, (s->waiting == 0)) != 0) {}
824 // reacquire the lock for our called
825 spin_lock_irqsave(&(s->lock), *flags);
831 // The assumption is that we enter this with the stream locked
832 // and we will return with it UNlocked
834 static int do_response_to_request(struct user_keyed_stream *s, unsigned long *flags)
838 printk("palacios: user keyed stream response while no request is in progress on %s\n",s->url);
842 // we are now waiting for a request
845 // release the stream
846 spin_unlock_irqrestore(&(s->lock), *flags);
848 // wake up anyone waiting on it
849 wake_up_interruptible(&(s->host_wait_queue));
856 static unsigned int keyed_stream_poll_user(struct file *filp, poll_table *wait)
858 struct user_keyed_stream *s = (struct user_keyed_stream *) (filp->private_data);
865 spin_lock_irqsave(&(s->lock), flags);
868 spin_unlock_irqrestore(&(s->lock), flags);
869 return POLLIN | POLLRDNORM;
872 poll_wait(filp, &(s->user_wait_queue), wait);
874 spin_unlock_irqrestore(&(s->lock), flags);
879 static int keyed_stream_ioctl_user(struct inode *inode, struct file *filp, unsigned int ioctl, unsigned long arg)
881 void __user *argp = (void __user *)arg;
885 struct user_keyed_stream *s = (struct user_keyed_stream *) (filp->private_data);
889 case V3_KSTREAM_REQUEST_SIZE_IOCTL:
891 // inform request size
893 spin_lock_irqsave(&(s->lock), flags);
896 spin_unlock_irqrestore(&(s->lock), flags);
900 size = sizeof(struct palacios_user_keyed_stream_op) + s->op->buf_len;
902 if (copy_to_user((void * __user) argp, &size, sizeof(uint64_t))) {
903 spin_unlock_irqrestore(&(s->lock), flags);
904 printk("palacios: palacios user key size request failed to copy data\n");
908 spin_unlock_irqrestore(&(s->lock), flags);
914 case V3_KSTREAM_REQUEST_PULL_IOCTL:
918 spin_lock_irqsave(&(s->lock), flags);
921 spin_unlock_irqrestore(&(s->lock), flags);
922 printk("palacios: palacios user key pull request when not waiting\n");
926 size = sizeof(struct palacios_user_keyed_stream_op) + s->op->buf_len;
929 if (copy_to_user((void __user *) argp, s->op, size)) {
930 spin_unlock_irqrestore(&(s->lock), flags);
931 printk("palacios: palacios user key pull request failed to copy data\n");
935 spin_unlock_irqrestore(&(s->lock), flags);
942 case V3_KSTREAM_RESPONSE_PUSH_IOCTL:
946 spin_lock_irqsave(&(s->lock), flags);
949 spin_unlock_irqrestore(&(s->lock), flags);
950 printk("palacios: palacios user key push response when not waiting\n");
954 if (copy_from_user(&size, (void __user *) argp, sizeof(uint64_t))) {
955 printk("palacios: palacios user key push response failed to copy size\n");
956 spin_unlock_irqrestore(&(s->lock), flags);
960 if (resize_op(&(s->op),size-sizeof(struct palacios_user_keyed_stream_op))) {
961 printk("palacios: unable to resize op in user key push response\n");
962 spin_unlock_irqrestore(&(s->lock), flags);
966 if (copy_from_user(s->op, (void __user *) argp, size)) {
967 spin_unlock_irqrestore(&(s->lock), flags);
971 do_response_to_request(s,&flags);
972 // this will have unlocked s for us
979 printk("palacios: unknown ioctl in user keyed stream\n");
988 static long keyed_stream_compat_ioctl_user(struct file * filp, unsigned int ioctl, unsigned long arg)
990 return keyed_stream_ioctl_user(NULL, filp, ioctl, arg);
993 static int keyed_stream_release_user(struct inode *inode, struct file *filp)
995 struct user_keyed_stream *s = filp->private_data;
998 spin_lock_irqsave(&(user_streams->lock),f1);
999 spin_lock_irqsave(&(s->lock), f2);
1001 list_del(&(s->node));
1003 spin_unlock_irqrestore(&(s->lock), f2);
1004 spin_unlock_irqrestore(&(user_streams->lock), f1);
1012 static struct file_operations user_keyed_stream_fops = {
1013 .poll = keyed_stream_poll_user,
1014 #ifdef HAVE_COMPAT_IOCTL
1015 .compat_ioctl = keyed_stream_compat_ioctl_user,
1017 .ioctl = keyed_stream_ioctl_user,
1019 .release = keyed_stream_release_user,
1024 user_keyed_streams are allocated on user connect, and deallocated on user release
1026 palacios-side opens and closes only manipulate the open type
1029 int keyed_stream_connect_user(struct v3_guest *guest, unsigned int cmd, unsigned long arg, void *priv_data)
1032 unsigned long flags;
1035 struct user_keyed_stream *s;
1037 if (!user_streams) {
1038 printk("palacios: no user space keyed streams!\n");
1043 if (copy_from_user(&len,(void __user *)arg,sizeof(len))) {
1044 printk("palacios: cannot copy url len from user\n");
1048 url = kmalloc(len,GFP_KERNEL);
1051 printk("palacios: cannot allocate url for user keyed stream\n");
1055 if (copy_from_user(url,((void __user *)arg)+sizeof(len),len)) {
1056 printk("palacios: cannot copy url from user\n");
1062 // Check for duplicate handler
1063 spin_lock_irqsave(&(user_streams->lock), flags);
1064 list_for_each_entry(s, &(user_streams->streams), node) {
1065 if (!strncasecmp(url, s->url, len)) {
1066 printk("palacios: user keyed stream connection with url \"%s\" already exists\n", url);
1071 spin_unlock_irqrestore(&(user_streams->lock), flags);
1073 // Create connection
1074 s = kmalloc(sizeof(struct user_keyed_stream), GFP_KERNEL);
1077 printk("palacios: cannot allocate new user keyed stream for %s\n",url);
1083 // Get file descriptor
1084 fd = anon_inode_getfd("v3-kstream", &user_keyed_stream_fops, s, 0);
1087 printk("palacios: cannot allocate file descriptor for new user keyed stream for %s\n",url);
1093 memset(s, 0, sizeof(struct user_keyed_stream));
1095 s->stype=STREAM_USER;
1098 init_waitqueue_head(&(s->user_wait_queue));
1099 init_waitqueue_head(&(s->host_wait_queue));
1101 // Insert connection into list
1102 spin_lock_irqsave(&(user_streams->lock), flags);
1103 list_add(&(s->node), &(user_streams->streams));
1104 spin_unlock_irqrestore(&(user_streams->lock), flags);
1109 static struct user_keyed_stream *keyed_stream_user_find(char *url)
1111 unsigned long flags;
1112 struct user_keyed_stream *s;
1114 if (!user_streams) {
1115 printk("palacios: no user space keyed streams available\n");
1119 spin_lock_irqsave(&(user_streams->lock), flags);
1120 list_for_each_entry(s, &(user_streams->streams), node) {
1121 if (!strcasecmp(url, s->url)) {
1122 spin_unlock_irqrestore(&(user_streams->lock), flags);
1127 spin_unlock_irqrestore(&(user_streams->lock), flags);
1133 static v3_keyed_stream_t open_stream_user(char *url, v3_keyed_stream_open_t ot)
1135 unsigned long flags;
1136 struct user_keyed_stream *s;
1138 s = keyed_stream_user_find(url);
1141 printk("palacios: cannot open user stream %s as it does not exist yet\n",url);
1145 spin_lock_irqsave(&(s->lock), flags);
1148 spin_unlock_irqrestore(&(s->lock), flags);
1149 printk("palacios: cannot open user stream %s as it is already in waiting state\n",url);
1153 s->otype = ot==V3_KS_WR_ONLY_CREATE ? V3_KS_WR_ONLY : ot;
1155 spin_unlock_irqrestore(&(s->lock), flags);
1161 // close stream does not do anything. Creation of the stream and its cleanup
1162 // are driven by the user side, not the palacios side
1163 // might eventually want to reference count this, though
1164 static void close_stream_user(v3_keyed_stream_t stream)
1169 static void preallocate_hint_key_user(v3_keyed_stream_t stream,
1179 static v3_keyed_stream_key_t open_key_user(v3_keyed_stream_t stream, char *key)
1181 unsigned long flags;
1182 struct user_keyed_stream *s = (struct user_keyed_stream *) stream;
1183 uint64_t len = strlen(key)+1;
1186 spin_lock_irqsave(&(s->lock), flags);
1189 if (resize_op(&(s->op),len)) {
1190 spin_unlock_irqrestore(&(s->lock),flags);
1191 printk("palacios: cannot resize op in opening key %s on user keyed stream %s\n",key,s->url);
1195 s->op->type = PALACIOS_KSTREAM_OPEN_KEY;
1196 s->op->buf_len = len;
1197 strncpy(s->op->buf,key,len);
1199 // enter with it locked
1200 if (do_request_to_response(s,&flags)) {
1201 spin_unlock_irqrestore(&(s->lock),flags);
1202 printk("palacios: request/response handling failed\n");
1205 // return with it locked
1207 user_key=s->op->user_key;
1209 spin_unlock_irqrestore(&(s->lock),flags);
1214 static void close_key_user(v3_keyed_stream_t stream, v3_keyed_stream_key_t key)
1216 struct user_keyed_stream *s = (struct user_keyed_stream *) stream;
1218 unsigned long flags;
1220 spin_lock_irqsave(&(s->lock), flags);
1222 if (resize_op(&(s->op),len)) {
1223 spin_unlock_irqrestore(&(s->lock),flags);
1224 printk("palacios: cannot resize op in closing key 0x%p on user keyed stream %s\n",key,s->url);
1228 s->op->type = PALACIOS_KSTREAM_CLOSE_KEY;
1229 s->op->buf_len = len;
1230 s->op->user_key = key;
1232 // enter with it locked
1233 if (do_request_to_response(s,&flags)) {
1234 spin_unlock_irqrestore(&(s->lock),flags);
1235 printk("palacios: request/response handling failed\n");
1238 // return with it locked
1240 spin_unlock_irqrestore(&(s->lock),flags);
1247 static sint64_t read_key_user(v3_keyed_stream_t stream, v3_keyed_stream_key_t key,
1248 void *buf, sint64_t rlen)
1251 struct user_keyed_stream *s = (struct user_keyed_stream *) stream;
1254 unsigned long flags;
1256 spin_lock_irqsave(&(s->lock), flags);
1258 if (s->otype != V3_KS_RD_ONLY) {
1259 spin_unlock_irqrestore(&(s->lock),flags);
1260 printk("palacios: attempt to read key from stream that is not in read state on %s\n",s->url);
1263 if (resize_op(&(s->op),len)) {
1264 spin_unlock_irqrestore(&(s->lock),flags);
1265 printk("palacios: cannot resize op in reading key 0x%p on user keyed stream %s\n",key,s->url);
1269 s->op->type = PALACIOS_KSTREAM_READ_KEY;
1270 s->op->buf_len = len ;
1272 s->op->user_key = key;
1274 // enter with it locked
1275 if (do_request_to_response(s,&flags)) {
1276 spin_unlock_irqrestore(&(s->lock),flags);
1277 printk("palacios: request/response handling failed\n");
1280 // return with it locked
1283 if (s->op->xfer>0) {
1284 memcpy(buf,s->op->buf,s->op->xfer);
1289 spin_unlock_irqrestore(&(s->lock),flags);
1295 static sint64_t write_key_user(v3_keyed_stream_t stream, v3_keyed_stream_key_t key,
1296 void *buf, sint64_t wlen)
1299 struct user_keyed_stream *s = (struct user_keyed_stream *) stream;
1300 struct palacios_user_keyed_stream_op *op;
1301 uint64_t len = wlen ;
1303 unsigned long flags;
1305 spin_lock_irqsave(&(s->lock), flags);
1307 if (s->otype != V3_KS_WR_ONLY) {
1308 spin_unlock_irqrestore(&(s->lock),flags);
1309 printk("palacios: attempt to write key on stream that is not in write state on %s\n",s->url);
1312 if (resize_op(&(s->op),len)) {
1313 spin_unlock_irqrestore(&(s->lock),flags);
1314 printk("palacios: cannot resize op in reading key 0x%p on user keyed stream %s\n",key,s->url);
1320 s->op->type = PALACIOS_KSTREAM_WRITE_KEY;
1321 s->op->buf_len = len;
1323 s->op->user_key = key;
1325 memcpy(s->op->buf,buf,wlen);
1327 // enter with it locked
1328 if (do_request_to_response(s,&flags)) {
1329 spin_unlock_irqrestore(&(s->lock),flags);
1330 printk("palacios: request/response handling failed\n");
1333 // return with it locked
1337 spin_unlock_irqrestore(&(s->lock),flags);
1345 /***************************************************************************************************
1347 *************************************************************************************************/
1349 static v3_keyed_stream_t open_stream(char *url,
1350 v3_keyed_stream_open_t ot)
1352 if (!strncasecmp(url,"mem:",4)) {
1353 return open_stream_mem(url,ot);
1354 } else if (!strncasecmp(url,"file:",5)) {
1355 return open_stream_file(url,ot);
1356 } else if (!strncasecmp(url,"user:",5)) {
1357 return open_stream_user(url,ot);
1359 printk("palacios: unsupported type in attempt to open keyed stream \"%s\"\n",url);
1364 static void close_stream(v3_keyed_stream_t stream)
1366 struct generic_keyed_stream *gks = (struct generic_keyed_stream *) stream;
1367 switch (gks->stype){
1369 return close_stream_mem(stream);
1372 return close_stream_file(stream);
1375 return close_stream_user(stream);
1378 printk("palacios: unknown stream type %d in close\n",gks->stype);
1383 static void preallocate_hint_key(v3_keyed_stream_t stream,
1387 struct generic_keyed_stream *gks = (struct generic_keyed_stream *) stream;
1388 switch (gks->stype){
1390 preallocate_hint_key_mem(stream,key,size);
1393 preallocate_hint_key_file(stream,key,size);
1396 return preallocate_hint_key_user(stream,key,size);
1399 printk("palacios: unknown stream type %d in preallocate_hint_key\n",gks->stype);
1406 static v3_keyed_stream_key_t open_key(v3_keyed_stream_t stream,
1409 struct generic_keyed_stream *gks = (struct generic_keyed_stream *) stream;
1410 switch (gks->stype){
1412 return open_key_mem(stream,key);
1415 return open_key_file(stream,key);
1418 return open_key_user(stream,key);
1421 printk("palacios: unknown stream type %d in open_key\n",gks->stype);
1428 static void close_key(v3_keyed_stream_t stream,
1429 v3_keyed_stream_key_t key)
1431 struct generic_keyed_stream *gks = (struct generic_keyed_stream *) stream;
1432 switch (gks->stype){
1434 return close_key_mem(stream,key);
1437 return close_key_file(stream,key);
1440 return close_key_user(stream,key);
1443 printk("palacios: unknown stream type %d in close_key\n",gks->stype);
1450 static sint64_t write_key(v3_keyed_stream_t stream,
1451 v3_keyed_stream_key_t key,
1455 struct generic_keyed_stream *gks = (struct generic_keyed_stream *) stream;
1456 switch (gks->stype){
1458 return write_key_mem(stream,key,buf,len);
1461 return write_key_file(stream,key,buf,len);
1464 return write_key_user(stream,key,buf,len);
1467 printk("palacios: unknown stream type %d in write_key\n",gks->stype);
1475 static sint64_t read_key(v3_keyed_stream_t stream,
1476 v3_keyed_stream_key_t key,
1480 struct generic_keyed_stream *gks = (struct generic_keyed_stream *) stream;
1481 switch (gks->stype){
1483 return read_key_mem(stream,key,buf,len);
1486 return read_key_file(stream,key,buf,len);
1489 return read_key_user(stream,key,buf,len);
1492 printk("palacios: unknown stream type %d in read_key\n",gks->stype);
1502 /***************************************************************************************************
1503 Hooks to palacios and inititialization
1504 *************************************************************************************************/
1507 static struct v3_keyed_stream_hooks hooks = {
1508 .open = open_stream,
1509 .close = close_stream,
1510 .preallocate_hint_key = preallocate_hint_key,
1511 .open_key = open_key,
1512 .close_key = close_key,
1513 .read_key = read_key,
1514 .write_key = write_key
1518 static int init_keyed_streams( void )
1520 mem_streams = palacios_create_htable(DEF_NUM_STREAMS,hash_func,hash_comp);
1523 printk("palacios: failed to allocated stream pool for in-memory streams\n");
1527 user_streams = kmalloc(sizeof(struct user_keyed_streams),GFP_KERNEL);
1529 if (!user_streams) {
1530 printk("palacios: failed to allocated list for user streams\n");
1534 INIT_LIST_HEAD(&(user_streams->streams));
1536 spin_lock_init(&(user_streams->lock));
1538 V3_Init_Keyed_Streams(&hooks);
1544 static int deinit_keyed_streams( void )
1546 palacios_free_htable(mem_streams,1,1);
1548 kfree(user_streams);
1550 printk("Deinit of Palacios Keyed Streams likely leaked memory\n");
1556 static int guest_init_keyed_streams(struct v3_guest * guest, void ** vm_data )
1559 add_guest_ctrl(guest, V3_VM_KSTREAM_USER_CONNECT, keyed_stream_connect_user, 0);
1565 static int guest_deinit_keyed_streams(struct v3_guest * guest, void * vm_data)
1574 static struct linux_ext key_stream_ext = {
1575 .name = "KEYED_STREAM_INTERFACE",
1576 .init = init_keyed_streams,
1577 .deinit = deinit_keyed_streams,
1578 .guest_init = guest_init_keyed_streams,
1579 .guest_deinit = guest_deinit_keyed_streams,
1583 register_extension(&key_stream_ext);