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;
765 // List of all of the user streams
767 static struct user_keyed_streams *user_streams;
771 static int resize_op(struct palacios_user_keyed_stream_op **op, uint64_t buf_len)
773 struct palacios_user_keyed_stream_op *old = *op;
774 struct palacios_user_keyed_stream_op *new;
777 new = kmalloc(sizeof(struct palacios_user_keyed_stream_op)+buf_len,GFP_ATOMIC);
781 new->len=sizeof(struct palacios_user_keyed_stream_op)+buf_len;
782 new->buf_len=buf_len;
787 if ((old->len-sizeof(struct palacios_user_keyed_stream_op)) >= buf_len) {
788 old->buf_len=buf_len;
793 return resize_op(op,buf_len);
799 // The assumption is that we enter this with the stream locked
800 // and we will return with it locked; additionally, the op structure
801 // will be overwritten with the response
803 static int do_request_to_response(struct user_keyed_stream *s, unsigned long *flags)
807 printk("palacios: user keyed stream request attempted while one is already in progress on %s\n",s->url);
811 // we are now waiting for a response
814 // release the stream
815 spin_unlock_irqrestore(&(s->lock), *flags);
817 // wake up anyone waiting on it
818 wake_up_interruptible(&(s->user_wait_queue));
820 // wait for someone to give us a response
821 wait_event_interruptible(s->host_wait_queue, !(s->waiting));
823 // reacquire the lock for our called
824 spin_lock_irqsave(&(s->lock), *flags);
830 // The assumption is that we enter this with the stream locked
831 // and we will return with it UNlocked
833 static int do_response_to_request(struct user_keyed_stream *s, unsigned long *flags)
836 printk("palacios: user keyed stream response while no request is in progress on %s\n",s->url);
840 // we are now waiting for a request
843 // release the stream
844 spin_unlock_irqrestore(&(s->lock), *flags);
846 // wake up anyone waiting on it
847 wake_up_interruptible(&(s->host_wait_queue));
854 static unsigned int keyed_stream_poll_user(struct file *filp, poll_table *wait)
856 struct user_keyed_stream *s = (struct user_keyed_stream *) (filp->private_data);
858 unsigned int mask = 0;
864 poll_wait(filp, &(s->user_wait_queue), wait);
866 spin_lock_irqsave(&(s->lock), flags);
868 mask |= POLLIN | POLLRDNORM;
870 spin_unlock_irqrestore(&(s->lock), flags);
876 static int keyed_stream_ioctl_user(struct inode *inode, struct file *filp, unsigned int ioctl, unsigned long arg)
878 void __user *argp = (void __user *)arg;
882 struct user_keyed_stream *s = (struct user_keyed_stream *) (filp->private_data);
886 case V3_KSTREAM_REQUEST_SIZE_IOCTL:
888 // inform request size
890 spin_lock_irqsave(&(s->lock), flags);
893 spin_unlock_irqrestore(&(s->lock), flags);
897 size = sizeof(struct palacios_user_keyed_stream_op) + s->op->buf_len;
899 if (copy_to_user(argp, &size, sizeof(uint64_t))) {
900 spin_unlock_irqrestore(&(s->lock), flags);
901 printk("palacios: palacios user key size request failed to copy data\n");
905 spin_unlock_irqrestore(&(s->lock), flags);
911 case V3_KSTREAM_REQUEST_PULL_IOCTL:
915 spin_lock_irqsave(&(s->lock), flags);
918 spin_unlock_irqrestore(&(s->lock), flags);
919 printk("palacios: palacios user key pull request when not waiting\n");
923 size = sizeof(struct palacios_user_keyed_stream_op) + s->op->buf_len;
926 if (copy_to_user(argp, s->op, size)) {
927 spin_unlock_irqrestore(&(s->lock), flags);
928 printk("palacios: palacios user key pull request failed to copy data\n");
932 spin_unlock_irqrestore(&(s->lock), flags);
939 case V3_KSTREAM_RESPONSE_PUSH_IOCTL:
943 spin_lock_irqsave(&(s->lock), flags);
946 spin_unlock_irqrestore(&(s->lock), flags);
947 printk("palacios: palacios user key push response when not waiting\n");
951 if (copy_from_user(&size, argp, sizeof(uint64_t))) {
952 printk("palacios: palacios user key push response failed to copy size\n");
953 spin_unlock_irqrestore(&(s->lock), flags);
957 if (resize_op(&(s->op),size-sizeof(struct palacios_user_keyed_stream_op))) {
958 printk("palacios: unable to resize op in user key push response\n");
959 spin_unlock_irqrestore(&(s->lock), flags);
963 if (copy_from_user(&(s->op), argp, size)) {
964 spin_unlock_irqrestore(&(s->lock), flags);
968 do_response_to_request(s,&flags);
969 // this will have unlocked s for us
976 printk("palacios: unknown ioctl in user keyed stream\n");
985 static int keyed_stream_release_user(struct inode *inode, struct file *filp)
987 struct user_keyed_stream *s = filp->private_data;
990 spin_lock_irqsave(&(user_streams->lock),f1);
991 spin_lock_irqsave(&(s->lock), f2);
993 // FIXME Need to handle case of a pending request
995 list_del(&(s->node));
997 spin_unlock_irqrestore(&(s->lock), f2);
998 spin_unlock_irqrestore(&(user_streams->lock), f1);
1006 static struct file_operations user_keyed_stream_fops = {
1007 .poll = keyed_stream_poll_user,
1008 .ioctl = keyed_stream_ioctl_user,
1009 .release = keyed_stream_release_user,
1014 user_keyed_streams are allocated on user connect, and deallocated on user release
1016 palacios-side opens and closes only manipulate the open type
1019 int keyed_stream_connect_user(struct v3_guest *guest, unsigned int cmd, unsigned long arg, void *priv_data)
1022 unsigned long flags;
1025 struct user_keyed_stream *s;
1027 if (!user_streams) {
1028 printk("palacios: no user space keyed streams!\n");
1033 if (copy_from_user(&len,(void __user *)arg,sizeof(len))) {
1034 printk("palacios: cannot copy url len from user\n");
1038 url = kmalloc(len,GFP_KERNEL);
1041 printk("palacios: cannot allocate url for user keyed stream\n");
1045 if (copy_from_user(url,((void __user *)arg)+sizeof(len),len)) {
1046 printk("palacios: cannot copy url from user\n");
1052 // Check for duplicate handler
1053 spin_lock_irqsave(&(user_streams->lock), flags);
1054 list_for_each_entry(s, &(user_streams->streams), node) {
1055 if (!strncasecmp(url, s->url, len)) {
1056 printk("palacios: user keyed stream connection with url \"%s\" already exists\n", url);
1061 spin_unlock_irqrestore(&(user_streams->lock), flags);
1063 // Create connection
1064 s = kmalloc(sizeof(struct user_keyed_stream), GFP_KERNEL);
1067 printk("palacios: cannot allocate new user keyed stream for %s\n",url);
1073 // Get file descriptor
1074 fd = anon_inode_getfd("v3-kstream", &user_keyed_stream_fops, s, 0);
1077 printk("palacios: cannot allocate file descriptor for new user keyed stream for %s\n",url);
1083 memset(s, 0, sizeof(struct user_keyed_stream));
1085 s->stype=STREAM_USER;
1088 init_waitqueue_head(&(s->user_wait_queue));
1089 init_waitqueue_head(&(s->host_wait_queue));
1091 // Insert connection into list
1092 spin_lock_irqsave(&(user_streams->lock), flags);
1093 list_add(&(s->node), &(user_streams->streams));
1094 spin_unlock_irqrestore(&(user_streams->lock), flags);
1099 static struct user_keyed_stream *keyed_stream_user_find(char *url)
1101 unsigned long flags;
1102 struct user_keyed_stream *s;
1104 if (!user_streams) {
1105 printk("palacios: no user space keyed streams available\n");
1109 spin_lock_irqsave(&(user_streams->lock), flags);
1110 list_for_each_entry(s, &(user_streams->streams), node) {
1111 if (!strcasecmp(url, s->url)) {
1112 spin_unlock_irqrestore(&(user_streams->lock), flags);
1117 spin_unlock_irqrestore(&(user_streams->lock), flags);
1123 static v3_keyed_stream_t open_stream_user(char *url, v3_keyed_stream_open_t ot)
1125 unsigned long flags;
1126 struct user_keyed_stream *s;
1128 s = keyed_stream_user_find(url);
1131 printk("palacios: cannot open user stream %s as it does not exist yet\n",url);
1135 spin_lock_irqsave(&(s->lock), flags);
1138 spin_unlock_irqrestore(&(s->lock), flags);
1139 printk("palacios: cannot open user stream %s as it is already in waiting state\n",url);
1144 s->otype = ot==V3_KS_WR_ONLY_CREATE ? V3_KS_WR_ONLY : ot;
1146 spin_unlock_irqrestore(&(s->lock), flags);
1152 // close stream does not do anything. Creation of the stream and its cleanup
1153 // are driven by the user side, not the palacios side
1154 // might eventually want to reference count this, though
1155 static void close_stream_user(v3_keyed_stream_t stream)
1160 static void preallocate_hint_key_user(v3_keyed_stream_t stream,
1170 static v3_keyed_stream_key_t open_key_user(v3_keyed_stream_t stream, char *key)
1172 unsigned long flags;
1173 struct user_keyed_stream *s = (struct user_keyed_stream *) stream;
1174 struct palacios_user_keyed_stream_op *op;
1175 uint64_t len = strlen(key)+1;
1178 spin_lock_irqsave(&(s->lock), flags);
1180 if (resize_op(&(s->op),len)) {
1181 spin_unlock_irqrestore(&(s->lock),flags);
1182 printk("palacios: cannot resize op in opening key %s on user keyed stream %s\n",key,s->url);
1188 op->type = PALACIOS_KSTREAM_OPEN_KEY;
1190 strncpy(op->buf,key,len);
1193 // enter with it locked
1194 if (do_request_to_response(s,&flags)) {
1195 spin_unlock_irqrestore(&(s->lock),flags);
1196 printk("palacios: request/response handling failed\n");
1199 // return with it locked
1201 user_key=s->op->user_key;
1203 spin_unlock_irqrestore(&(s->lock),flags);
1208 static void close_key_user(v3_keyed_stream_t stream, v3_keyed_stream_key_t key)
1210 struct user_keyed_stream *s = (struct user_keyed_stream *) stream;
1211 struct palacios_user_keyed_stream_op *op;
1213 unsigned long flags;
1215 spin_lock_irqsave(&(s->lock), flags);
1217 if (resize_op(&(s->op),len)) {
1218 spin_unlock_irqrestore(&(s->lock),flags);
1219 printk("palacios: cannot resize op in closing key 0x%p on user keyed stream %s\n",key,s->url);
1225 op->type = PALACIOS_KSTREAM_CLOSE_KEY;
1229 // enter with it locked
1230 if (do_request_to_response(s,&flags)) {
1231 spin_unlock_irqrestore(&(s->lock),flags);
1232 printk("palacios: request/response handling failed\n");
1235 // return with it locked
1237 spin_unlock_irqrestore(&(s->lock),flags);
1244 static sint64_t read_key_user(v3_keyed_stream_t stream, v3_keyed_stream_key_t key,
1245 void *buf, sint64_t rlen)
1248 struct user_keyed_stream *s = (struct user_keyed_stream *) stream;
1249 struct palacios_user_keyed_stream_op *op;
1252 unsigned long flags;
1254 spin_lock_irqsave(&(s->lock), flags);
1256 if (s->otype != V3_KS_RD_ONLY) {
1257 spin_unlock_irqrestore(&(s->lock),flags);
1258 printk("palacios: attempt to read key from stream that is not in read state on %s\n",s->url);
1261 if (resize_op(&(s->op),len)) {
1262 spin_unlock_irqrestore(&(s->lock),flags);
1263 printk("palacios: cannot resize op in reading key 0x%p on user keyed stream %s\n",key,s->url);
1269 op->type = PALACIOS_KSTREAM_READ_KEY;
1273 // enter with it locked
1274 if (do_request_to_response(s,&flags)) {
1275 spin_unlock_irqrestore(&(s->lock),flags);
1276 printk("palacios: request/response handling failed\n");
1279 // return with it locked
1282 memcpy(buf,op->buf,op->xfer);
1287 spin_unlock_irqrestore(&(s->lock),flags);
1293 static sint64_t write_key_user(v3_keyed_stream_t stream, v3_keyed_stream_key_t key,
1294 void *buf, sint64_t wlen)
1297 struct user_keyed_stream *s = (struct user_keyed_stream *) stream;
1298 struct palacios_user_keyed_stream_op *op;
1299 uint64_t len = wlen ;
1301 unsigned long flags;
1303 spin_lock_irqsave(&(s->lock), flags);
1305 if (s->otype != V3_KS_WR_ONLY) {
1306 spin_unlock_irqrestore(&(s->lock),flags);
1307 printk("palacios: attempt to write key on stream that is not in write state on %s\n",s->url);
1310 if (resize_op(&(s->op),len)) {
1311 spin_unlock_irqrestore(&(s->lock),flags);
1312 printk("palacios: cannot resize op in reading key 0x%p on user keyed stream %s\n",key,s->url);
1318 op->type = PALACIOS_KSTREAM_WRITE_KEY;
1322 memcpy(op->buf,buf,wlen);
1324 // enter with it locked
1325 if (do_request_to_response(s,&flags)) {
1326 spin_unlock_irqrestore(&(s->lock),flags);
1327 printk("palacios: request/response handling failed\n");
1330 // return with it locked
1334 spin_unlock_irqrestore(&(s->lock),flags);
1342 /***************************************************************************************************
1344 *************************************************************************************************/
1346 static v3_keyed_stream_t open_stream(char *url,
1347 v3_keyed_stream_open_t ot)
1349 if (!strncasecmp(url,"mem:",4)) {
1350 return open_stream_mem(url,ot);
1351 } else if (!strncasecmp(url,"file:",5)) {
1352 return open_stream_file(url,ot);
1353 } else if (!strncasecmp(url,"user:",5)) {
1354 return open_stream_user(url,ot);
1356 printk("palacios: unsupported type in attempt to open keyed stream \"%s\"\n",url);
1361 static void close_stream(v3_keyed_stream_t stream)
1363 struct generic_keyed_stream *gks = (struct generic_keyed_stream *) stream;
1364 switch (gks->stype){
1366 return close_stream_mem(stream);
1369 return close_stream_file(stream);
1372 return close_stream_user(stream);
1375 printk("palacios: unknown stream type %d in close\n",gks->stype);
1380 static void preallocate_hint_key(v3_keyed_stream_t stream,
1384 struct generic_keyed_stream *gks = (struct generic_keyed_stream *) stream;
1385 switch (gks->stype){
1387 preallocate_hint_key_mem(stream,key,size);
1390 preallocate_hint_key_file(stream,key,size);
1393 return preallocate_hint_key_user(stream,key,size);
1396 printk("palacios: unknown stream type %d in preallocate_hint_key\n",gks->stype);
1403 static v3_keyed_stream_key_t open_key(v3_keyed_stream_t stream,
1406 struct generic_keyed_stream *gks = (struct generic_keyed_stream *) stream;
1407 switch (gks->stype){
1409 return open_key_mem(stream,key);
1412 return open_key_file(stream,key);
1415 return open_key_user(stream,key);
1418 printk("palacios: unknown stream type %d in open_key\n",gks->stype);
1425 static void close_key(v3_keyed_stream_t stream,
1426 v3_keyed_stream_key_t key)
1428 struct generic_keyed_stream *gks = (struct generic_keyed_stream *) stream;
1429 switch (gks->stype){
1431 return close_key_mem(stream,key);
1434 return close_key_file(stream,key);
1437 return close_key_user(stream,key);
1440 printk("palacios: unknown stream type %d in close_key\n",gks->stype);
1447 static sint64_t write_key(v3_keyed_stream_t stream,
1448 v3_keyed_stream_key_t key,
1452 struct generic_keyed_stream *gks = (struct generic_keyed_stream *) stream;
1453 switch (gks->stype){
1455 return write_key_mem(stream,key,buf,len);
1458 return write_key_file(stream,key,buf,len);
1461 return write_key_user(stream,key,buf,len);
1464 printk("palacios: unknown stream type %d in write_key\n",gks->stype);
1472 static sint64_t read_key(v3_keyed_stream_t stream,
1473 v3_keyed_stream_key_t key,
1477 struct generic_keyed_stream *gks = (struct generic_keyed_stream *) stream;
1478 switch (gks->stype){
1480 return read_key_mem(stream,key,buf,len);
1483 return read_key_file(stream,key,buf,len);
1486 return read_key_user(stream,key,buf,len);
1489 printk("palacios: unknown stream type %d in read_key\n",gks->stype);
1499 /***************************************************************************************************
1500 Hooks to palacios and inititialization
1501 *************************************************************************************************/
1504 static struct v3_keyed_stream_hooks hooks = {
1505 .open = open_stream,
1506 .close = close_stream,
1507 .preallocate_hint_key = preallocate_hint_key,
1508 .open_key = open_key,
1509 .close_key = close_key,
1510 .read_key = read_key,
1511 .write_key = write_key
1515 static int init_keyed_streams( void )
1517 mem_streams = palacios_create_htable(DEF_NUM_STREAMS,hash_func,hash_comp);
1520 printk("palacios: failed to allocated stream pool for in-memory streams\n");
1524 user_streams = kmalloc(sizeof(struct user_keyed_streams),GFP_KERNEL);
1526 if (!user_streams) {
1527 printk("palacios: failed to allocated list for user streams\n");
1531 INIT_LIST_HEAD(&(user_streams->streams));
1533 spin_lock_init(&(user_streams->lock));
1535 V3_Init_Keyed_Streams(&hooks);
1541 static int deinit_keyed_streams( void )
1543 palacios_free_htable(mem_streams,1,1);
1545 kfree(user_streams);
1547 printk("Deinit of Palacios Keyed Streams likely leaked memory\n");
1553 static int guest_init_keyed_streams(struct v3_guest * guest, void ** vm_data )
1556 add_guest_ctrl(guest, V3_VM_KSTREAM_USER_CONNECT, keyed_stream_connect_user, 0);
1562 static int guest_deinit_keyed_streams(struct v3_guest * guest, void * vm_data)
1571 static struct linux_ext key_stream_ext = {
1572 .name = "KEYED_STREAM_INTERFACE",
1573 .init = init_keyed_streams,
1574 .deinit = deinit_keyed_streams,
1575 .guest_init = guest_init_keyed_streams,
1576 .guest_deinit = guest_deinit_keyed_streams,
1580 register_extension(&key_stream_ext);