Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Clean up compat ioctl handlers in host-dev and keyed-stream host ifaces
[palacios.git] / linux_module / iface-keyed-stream.c
1 /*
2  * Palacios keyed stream interface
3  *
4  * Plus implementations for mem, file, and user space implementations
5  *
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)
8  */
9
10 #include <linux/fs.h>
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>
17
18 #include "palacios.h"
19 #include "util-hashtable.h"
20 #include "linux-exts.h"
21 #include "vm.h"
22
23 #define sint64_t int64_t
24 #include <interfaces/vmm_keyed_stream.h>
25
26 #include "iface-keyed-stream-user.h"
27
28 /*
29   This is an implementation of the Palacios keyed stream interface
30   that supports three flavors of streams:
31
32   "mem:"   Streams are stored in a hash table
33   The values for this hash table are hash tables associated with 
34   each stream.   
35
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. 
39
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
43    
44 */
45
46 #define STREAM_GENERIC 0
47 #define STREAM_MEM     1
48 #define STREAM_FILE    2
49 #define STREAM_USER    3
50
51 /*
52   All keyed streams and streams indicate their implementation type within the first field
53  */
54 struct generic_keyed_stream {
55     int stype;
56 };
57
58 struct generic_stream {
59     int stype;
60 };
61   
62
63
64
65 /****************************************************************************************
66    Memory-based implementation  ("mem:")
67 ****************************************************************************************/
68
69 #define DEF_NUM_STREAMS 16
70 #define DEF_NUM_KEYS    128
71 #define DEF_SIZE        128
72
73 /*
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
76  */
77 struct mem_keyed_stream {
78     int stype;
79     v3_keyed_stream_open_t ot;
80     struct hashtable *ht;
81 };
82
83 struct mem_stream {
84     int       stype;
85     char     *data;
86     uint32_t  size;
87     uint32_t  data_max;
88     uint32_t  ptr;
89 };
90
91 static struct mem_stream *create_mem_stream_internal(uint64_t size)
92 {
93     struct mem_stream *m = kmalloc(sizeof(struct mem_stream),GFP_KERNEL);
94
95     if (!m) {
96         return 0;
97     }
98
99
100     m->data = vmalloc(size);
101     
102     if (!m->data) { 
103         kfree(m);
104         return 0;
105     }
106
107     m->stype = STREAM_MEM;
108     m->size=size;
109     m->ptr=0;
110     m->data_max=0;
111     
112     return m;
113 }
114
115
116 static struct mem_stream *create_mem_stream(void)
117 {
118     return create_mem_stream_internal(DEF_SIZE);
119 }
120
121 static void destroy_mem_stream(struct mem_stream *m)
122 {
123     if (m) {
124         if (m->data) {
125             kfree(m->data);
126         }
127         m->data=0;
128         kfree(m);
129     }
130 }
131     
132 static int expand_mem_stream(struct mem_stream *m, uint32_t new_size)
133 {
134     void *data = vmalloc(new_size);
135     uint32_t nc;
136
137     if (!data) { 
138         return -1;
139     }
140     
141     nc = (new_size<m->data_max) ? new_size : m->data_max;
142
143     memcpy(data,m->data,nc);
144
145     kfree(m->data);
146
147     m->data=data;
148     m->size=new_size;
149     if (m->size<m->data_max) { 
150         m->data_max=m->size;
151     }
152    
153     return 0;
154 }
155
156 static uint32_t write_mem_stream(struct mem_stream *m,
157                                  void *data,
158                                  uint32_t len)
159 {
160     if ((m->ptr + len) > m->size) { 
161         if (expand_mem_stream(m,m->ptr + len)) { 
162             return 0;
163         }
164     }
165     memcpy(m->data+m->ptr,data,len);
166     m->ptr+=len;
167     m->data_max=m->ptr;
168     
169     return len;
170
171 }
172
173 static uint32_t read_mem_stream(struct mem_stream *m,
174                                 void *data,
175                                 uint32_t len)
176 {
177     if ((m->ptr + len) > m->data_max) { 
178         return 0;
179     }
180     memcpy(data,m->data+m->ptr,len);
181     m->ptr+=len;
182     
183     return len;
184
185 }
186
187
188 static void reset_mem_stream(struct mem_stream *m)
189 {
190     m->ptr=0;
191 }
192
193
194 static inline uint_t hash_func(addr_t key)
195 {
196     return palacios_hash_buffer((uchar_t*)key,strlen((uchar_t*)key));
197 }
198
199 static inline int hash_comp(addr_t k1, addr_t k2)
200 {
201     return strcasecmp((char*)k1,(char*)k2)==0;
202 }
203
204
205 // This stores all the memory keyed streams streams
206 static struct hashtable *mem_streams=0;
207
208
209 static v3_keyed_stream_t open_stream_mem(char *url,
210                                          v3_keyed_stream_open_t ot)
211 {
212
213     if (strncasecmp(url,"mem:",4)) { 
214         printk("palacios: illegitimate attempt to open memory stream \"%s\"\n",url);
215         return 0;
216     }
217
218     switch (ot) { 
219         case V3_KS_RD_ONLY:
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));
222             if (mks) { 
223                 mks->ot=ot;
224             }
225             return (v3_keyed_stream_t) mks;
226         }
227             break;
228
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));
231             if (!mks) { 
232                 char *mykey;
233
234                 mykey = kmalloc(strlen(url+4)+1,GFP_KERNEL);
235
236                 if (!mykey) { 
237                     printk("palacios: cannot allocate space for new in-memory keyed stream %s\n",url);
238                     return 0;
239                 }
240
241                 strcpy(mykey,url+4);
242                 
243                 mks = (struct mem_keyed_stream *) kmalloc(sizeof(struct mem_keyed_stream),GFP_KERNEL);
244
245                 if (!mks) { 
246                     kfree(mykey);
247                     printk("palacios: cannot allocate in-memory keyed stream %s\n",url);
248                     return 0;
249                 }
250             
251                 mks->ht = (void*) palacios_create_htable(DEF_NUM_KEYS,hash_func,hash_comp);
252                 if (!mks->ht) { 
253                     kfree(mks);
254                     kfree(mykey);
255                     printk("palacios: cannot allocate in-memory keyed stream %s\n",url);
256                     return 0;
257                 }
258
259                 
260                 if (!palacios_htable_insert(mem_streams,(addr_t)(mykey),(addr_t)mks)) { 
261                     palacios_free_htable(mks->ht,1,1);
262                     kfree(mks);
263                     kfree(mykey);
264                     printk("palacios: cannot insert in-memory keyed stream %s\n",url);
265                     return 0;
266                 }
267                 mks->stype=STREAM_MEM;
268             }
269
270             mks->ot=V3_KS_WR_ONLY;
271             
272             return mks;
273             
274         }
275             break;
276
277         default:
278             printk("palacios: unsupported open type in open_stream_mem\n");
279             break;
280     }
281     
282     return 0;
283         
284 }
285
286
287
288 static void close_stream_mem(v3_keyed_stream_t stream)
289 {
290     // nothing to do
291     return;
292 }
293
294
295 static v3_keyed_stream_key_t open_key_mem(v3_keyed_stream_t stream,
296                                           char *key)
297 {
298     struct mem_keyed_stream *mks = (struct mem_keyed_stream *) stream;
299     struct hashtable *s = mks->ht;
300
301     struct mem_stream *m;
302
303     m = (struct mem_stream *) palacios_htable_search(s,(addr_t)key);
304
305     if (!m) { 
306         char *mykey = kmalloc(strlen(key)+1,GFP_KERNEL);
307
308         if (!mykey) { 
309             printk("palacios: cannot allocate copy of key for key %s\n",key);
310             return 0;
311         }
312
313         strcpy(mykey,key);
314
315         m = create_mem_stream();
316         
317         if (!m) { 
318             kfree(mykey);
319             printk("palacios: cannot allocate mem keyed stream for key %s\n",key);
320             return 0;
321         }
322
323         if (!palacios_htable_insert(s,(addr_t)mykey,(addr_t)m)) {
324             destroy_mem_stream(m);
325             kfree(mykey);
326             printk("palacios: cannot insert mem keyed stream for key %s\n",key);
327             return 0;
328         }
329     }
330
331     reset_mem_stream(m);
332     return m;
333
334 }
335
336
337 static void preallocate_hint_key_mem(v3_keyed_stream_t stream,
338                                      char *key,
339                                      uint64_t size)
340 {
341     struct mem_keyed_stream *mks = (struct mem_keyed_stream *) stream;
342     struct hashtable *s = mks->ht;
343
344     struct mem_stream *m;
345
346     if (mks->ot != V3_KS_WR_ONLY) { 
347         return;
348     }
349
350     m = (struct mem_stream *) palacios_htable_search(s,(addr_t)key);
351
352     if (!m) {
353         char *mykey;
354         
355         mykey=kmalloc(strlen(key)+1,GFP_KERNEL);
356         
357         if (!mykey) { 
358             printk("palacios: cannot allocate key spce for preallocte for key %s\n",key);
359             return;
360         }
361         
362         strcpy(mykey,key);
363        
364         m = create_mem_stream_internal(size);
365         
366         if (!m) { 
367             printk("palacios: cannot preallocate mem keyed stream for key %s\n",key);
368             return;
369         }
370
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);
374             return;
375         }
376     } else {
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);
380                 return;
381             }
382         }
383     }
384
385     return;
386
387 }
388
389 static void close_key_mem(v3_keyed_stream_t stream, 
390                           v3_keyed_stream_key_t key)
391 {
392     // nothing to do
393     return;
394 }
395
396 static sint64_t write_key_mem(v3_keyed_stream_t stream, 
397                               v3_keyed_stream_key_t key,
398                               void *buf,
399                               sint64_t len)
400 {
401     struct mem_keyed_stream *mks = (struct mem_keyed_stream *) stream;
402     struct mem_stream *m = (struct mem_stream *) key;
403     uint32_t mylen;
404     uint32_t writelen;
405
406     if (mks->ot!=V3_KS_WR_ONLY) {
407         return -1;
408     }
409
410     if (len<0) { 
411         return -1;
412     }
413     
414     mylen = (uint32_t) len;
415
416     writelen=write_mem_stream(m,buf,mylen);
417
418     if (writelen!=mylen) { 
419         printk("palacios: failed to write all data for key\n");
420         return -1;
421     } else {
422         return (sint64_t)writelen;
423     }
424 }
425
426 static sint64_t read_key_mem(v3_keyed_stream_t stream, 
427                              v3_keyed_stream_key_t key,
428                              void *buf,
429                              sint64_t len)
430 {
431     struct mem_keyed_stream *mks = (struct mem_keyed_stream *) stream;
432     struct mem_stream *m = (struct mem_stream *) key;
433     uint32_t mylen;
434     uint32_t readlen;
435     
436     if (mks->ot!=V3_KS_RD_ONLY) {
437         return -1;
438     }
439
440     if (len<0) { 
441         return -1;
442     }
443     
444     mylen = (uint32_t) len;
445     
446     readlen=read_mem_stream(m,buf,mylen);
447     
448     if (readlen!=mylen) { 
449         printk("palacios: failed to read all data for key\n");
450         return -1;
451     } else {
452         return (sint64_t)readlen;
453     }
454 }
455
456
457 /***************************************************************************************************
458   File-based implementation  ("file:")
459 *************************************************************************************************/
460
461 /*
462   A file keyed stream contains the fd of the directory
463   and a path
464 */
465
466 struct file_keyed_stream {
467     int   stype;
468     v3_keyed_stream_open_t ot;
469     char  *path;
470 };
471
472 struct file_stream {
473     int   stype;
474     struct file *f;   // the opened file
475 };
476
477
478 static v3_keyed_stream_t open_stream_file(char *url,
479                                           v3_keyed_stream_open_t ot)
480 {
481     struct file_keyed_stream *fks;
482     struct nameidata nd;
483
484     if (strncasecmp(url,"file:",5)) { 
485         printk("palacios: illegitimate attempt to open file stream \"%s\"\n",url);
486         return 0;
487     }
488
489     fks = kmalloc(sizeof(struct file_keyed_stream),GFP_KERNEL);
490     
491     if (!fks) { 
492         printk("palacios: cannot allocate space for file stream\n");
493         return 0;
494     }
495
496     fks->path = (char*)kmalloc(strlen(url+5)+1,GFP_KERNEL);
497     
498     if (!(fks->path)) { 
499         printk("palacios: cannot allocate space for file stream\n");
500         kfree(fks);
501         return 0;
502     }
503     
504     strcpy(fks->path,url+5);
505     
506     fks->stype=STREAM_FILE;
507
508     fks->ot= ot==V3_KS_WR_ONLY_CREATE ? V3_KS_WR_ONLY : ot;
509
510     // Does the directory exist, and can we read/write it?
511    
512     if (path_lookup(fks->path,LOOKUP_DIRECTORY|LOOKUP_FOLLOW,&nd)) { 
513
514         // directory does does not exist.  
515
516         if (ot==V3_KS_RD_ONLY || ot==V3_KS_WR_ONLY) { 
517
518             // we are not being asked to create it
519             printk("palacios: attempt to open %s, which does not exist\n",fks->path);
520             goto fail_out;
521
522         } else {
523
524             // We are being asked to create it
525
526             struct dentry *de;
527             int err;
528
529             // Find its parent
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);
532                 goto fail_out;
533             }
534
535             // Can we write to the parent?
536
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);
539                 goto fail_out;
540             }
541
542             // OK, we can, so let's create it
543
544             de = lookup_create(&nd,1);
545
546             if (IS_ERR(de)) { 
547                 printk("palacios: cannot allocate dentry\n");
548                 goto fail_out;
549             }
550
551             err = vfs_mkdir(nd.path.dentry->d_inode, de, 0700);
552
553             // lookup_create locks this for us!
554
555             mutex_unlock(&(nd.path.dentry->d_inode->i_mutex));
556
557             if (err) {
558                 printk("palacios: attempt to create %s failed because mkdir failed\n",fks->path);
559                 goto fail_out;
560             }
561
562             // now the directory should exist and have reasonable permissions
563             return (v3_keyed_stream_t) fks;
564         }
565     } 
566
567     
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
570
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);
573         goto fail_out;
574     } else {
575         return (v3_keyed_stream_t) fks;
576     }
577
578
579  fail_out:
580     kfree(fks->path);
581     kfree(fks);
582     return 0;
583
584 }
585
586 static void close_stream_file(v3_keyed_stream_t stream)
587 {
588     struct file_keyed_stream *fks = (struct file_keyed_stream *) stream;
589     
590     kfree(fks->path);
591     kfree(fks);
592
593 }
594
595 static void preallocate_hint_key_file(v3_keyed_stream_t stream,
596                                       char *key,
597                                       uint64_t size)
598 {
599     return;
600 }
601
602 static v3_keyed_stream_key_t open_key_file(v3_keyed_stream_t stream,
603                                            char *key)
604 {
605     struct file_keyed_stream *fks = (struct file_keyed_stream *) stream;
606     struct file_stream *fs;
607     char *path;
608
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);
612     if (!path) {                                
613         printk("palacios: cannot allocate file keyed stream for key %s\n",key);
614         return 0;
615     }
616     strcpy(path,fks->path);
617     strcat(path,"/");
618     strcat(path,key);
619     
620     fs = (struct file_stream *) kmalloc(sizeof(struct file_stream *),GFP_KERNEL);
621     
622     if (!fs) { 
623         printk("palacios: cannot allocate file keyed stream for key %s\n",key);
624         kfree(path);
625         return 0;
626     }
627
628     fs->stype=STREAM_FILE;
629
630     fs->f = filp_open(path,O_RDWR|O_CREAT,0600);
631     
632     if (IS_ERR(fs->f)) {
633         printk("palacios: cannot open relevent file \"%s\" for stream \"file:%s\" and key \"%s\"\n",path,fks->path,key);
634         kfree(fs);
635         kfree(path);
636         return 0;
637     }
638
639     kfree(path);
640
641     return fs;
642 }
643
644
645 static void close_key_file(v3_keyed_stream_t stream, 
646                            v3_keyed_stream_key_t key)
647 {
648     struct file_stream *fs = (struct file_stream *) key;
649
650     filp_close(fs->f,NULL);
651
652     kfree(fs);
653 }
654
655 static sint64_t write_key_file(v3_keyed_stream_t stream, 
656                                v3_keyed_stream_key_t key,
657                                void *buf,
658                                sint64_t len)
659 {
660     struct file_keyed_stream *fks = (struct file_keyed_stream *) stream;
661     struct file_stream *fs = (struct file_stream *) key;
662     mm_segment_t old_fs;
663     ssize_t done, left, total;
664     
665     if (fks->ot!=V3_KS_WR_ONLY) { 
666         return -1;
667     }
668     
669     if (len<0) { 
670         return -1;
671     }
672
673     total=len;
674     left=len;
675
676     old_fs = get_fs();
677     set_fs(get_ds());
678
679     while (left>0) {
680         done = fs->f->f_op->write(fs->f, buf+(total-left), left, &(fs->f->f_pos));
681         if (done<=0) {
682             return -1;
683         } else {
684             left -= done;
685         }
686     }
687     set_fs(old_fs);
688
689     return len;
690 }
691
692
693
694 static sint64_t read_key_file(v3_keyed_stream_t stream, 
695                               v3_keyed_stream_key_t key,
696                               void *buf,
697                               sint64_t len)
698 {
699     struct file_keyed_stream *fks = (struct file_keyed_stream *) stream;
700     struct file_stream *fs = (struct file_stream *) key;
701     mm_segment_t old_fs;
702     ssize_t done, left, total;
703     
704     if (fks->ot!=V3_KS_RD_ONLY) { 
705         return -1;
706     }
707
708     if (len<0) { 
709         return -1;
710     }
711
712     total=len;
713     left=len;
714
715     old_fs = get_fs();
716     set_fs(get_ds());
717
718     while (left>0) {
719         done = fs->f->f_op->read(fs->f, buf+(total-left), left, &(fs->f->f_pos));
720         if (done<=0) {
721             return -1;
722         } else {
723             left -= done;
724         }
725     }
726     set_fs(old_fs);
727
728     return len;
729
730 }
731
732
733
734
735 /***************************************************************************************************
736   User implementation   ("user:")
737 *************************************************************************************************/
738
739
740 // List of all user keyed stream connections for the guest
741 struct user_keyed_streams {
742     spinlock_t lock;
743     struct list_head streams;
744 };
745
746
747 // A single keyed stream connection to user space
748 struct user_keyed_stream {
749     int stype;
750     v3_keyed_stream_open_t otype;
751
752     char *url;
753     spinlock_t lock;
754     int waiting;
755
756     wait_queue_head_t user_wait_queue;
757     wait_queue_head_t host_wait_queue;
758
759     struct palacios_user_keyed_stream_op *op;
760
761     struct list_head node;
762 };
763
764
765 //
766 // List of all of the user streams
767 //
768 static struct user_keyed_streams *user_streams;
769
770
771
772 static int resize_op(struct palacios_user_keyed_stream_op **op, uint64_t buf_len)
773 {
774     struct palacios_user_keyed_stream_op *old = *op;
775     struct palacios_user_keyed_stream_op *new;
776     
777     if (!old) {
778         new = kmalloc(sizeof(struct palacios_user_keyed_stream_op)+buf_len,GFP_ATOMIC);
779         if (!new) { 
780             return -1;
781         } else {
782             new->len=sizeof(struct palacios_user_keyed_stream_op)+buf_len;
783             new->buf_len=buf_len;
784             *op=new;
785             return 0;
786         }
787     } else {
788         if ((old->len-sizeof(struct palacios_user_keyed_stream_op)) >= buf_len) { 
789             old->buf_len=buf_len;
790             return 0;
791         } else {
792             kfree(old);
793             *op = 0 ;
794             return resize_op(op,buf_len);
795         }
796     }
797 }
798
799 //
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
803 // 
804 static int do_request_to_response(struct user_keyed_stream *s, unsigned long *flags)
805 {
806
807     if (s->waiting) {
808         printk("palacios: user keyed stream request attempted while one is already in progress on %s\n",s->url);
809         return -1;
810     }
811
812     // we are now waiting for a response
813     s->waiting = 1;
814
815     // release the stream
816     spin_unlock_irqrestore(&(s->lock), *flags);
817
818     // wake up anyone waiting on it
819     wake_up_interruptible(&(s->user_wait_queue));
820
821     // wait for someone to give us a response
822     while (wait_event_interruptible(s->host_wait_queue, (s->waiting == 0)) != 0) {}
823
824     // reacquire the lock for our called
825     spin_lock_irqsave(&(s->lock), *flags);
826
827     return 0;
828 }
829
830 //
831 // The assumption is that we enter this with the stream locked
832 // and we will return with it UNlocked
833 // 
834 static int do_response_to_request(struct user_keyed_stream *s, unsigned long *flags)
835 {
836
837     if (!(s->waiting)) {
838         printk("palacios: user keyed stream response while no request is in progress on %s\n",s->url);
839         return -1;
840     }
841
842     // we are now waiting for a request
843     s->waiting = 0;
844
845     // release the stream
846     spin_unlock_irqrestore(&(s->lock), *flags);
847
848     // wake up anyone waiting on it
849     wake_up_interruptible(&(s->host_wait_queue));
850     
851     return 0;
852 }
853
854
855
856 static unsigned int keyed_stream_poll_user(struct file *filp, poll_table *wait)
857 {
858     struct user_keyed_stream *s = (struct user_keyed_stream *) (filp->private_data);
859     unsigned long flags;
860     
861     if (!s) {
862         return POLLERR;
863     }
864     
865     spin_lock_irqsave(&(s->lock), flags);
866
867     if (s->waiting) {
868         spin_unlock_irqrestore(&(s->lock), flags);
869         return POLLIN | POLLRDNORM;
870     }
871
872     poll_wait(filp, &(s->user_wait_queue), wait);
873     
874     spin_unlock_irqrestore(&(s->lock), flags);
875
876     return 0;
877 }
878
879 static int keyed_stream_ioctl_user(struct inode *inode, struct file *filp, unsigned int ioctl, unsigned long arg)
880 {
881     void __user *argp = (void __user *)arg;
882     unsigned long flags;
883     uint64_t size;
884     
885     struct user_keyed_stream *s = (struct user_keyed_stream *) (filp->private_data);
886     
887     switch (ioctl) {
888
889         case V3_KSTREAM_REQUEST_SIZE_IOCTL:
890             
891             // inform request size
892             
893             spin_lock_irqsave(&(s->lock), flags);
894             
895             if (!(s->waiting)) {
896                 spin_unlock_irqrestore(&(s->lock), flags);
897                 return 0;
898             }
899
900             size =  sizeof(struct palacios_user_keyed_stream_op) + s->op->buf_len;
901             
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");
905                 return -EFAULT;
906             }
907             
908             spin_unlock_irqrestore(&(s->lock), flags);
909             
910             return 1;
911             
912             break;
913
914         case V3_KSTREAM_REQUEST_PULL_IOCTL: 
915                 
916             // pull the request
917             
918             spin_lock_irqsave(&(s->lock), flags);
919
920             if (!(s->waiting)) {
921                 spin_unlock_irqrestore(&(s->lock), flags);
922                 printk("palacios: palacios user key pull request when not waiting\n");
923                 return 0;
924             }
925
926             size =  sizeof(struct palacios_user_keyed_stream_op) + s->op->buf_len;
927
928
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");
932                 return -EFAULT;
933             }
934
935             spin_unlock_irqrestore(&(s->lock), flags);
936             
937             return 1;
938             
939          
940             break;
941
942     case V3_KSTREAM_RESPONSE_PUSH_IOCTL:
943
944         // push the response
945
946         spin_lock_irqsave(&(s->lock), flags);
947
948         if (!(s->waiting)) {
949             spin_unlock_irqrestore(&(s->lock), flags);
950             printk("palacios: palacios user key push response when not waiting\n");
951             return 0;
952         }
953         
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);
957             return -EFAULT;
958         }
959
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);
963             return -EFAULT;
964         }
965
966         if (copy_from_user(s->op, (void __user *) argp, size)) {
967             spin_unlock_irqrestore(&(s->lock), flags);
968             return -EFAULT;
969         }
970
971         do_response_to_request(s,&flags);
972         // this will have unlocked s for us
973
974         return 1;
975
976         break;
977         
978     default:
979         printk("palacios: unknown ioctl in user keyed stream\n");
980
981         return -EFAULT;
982
983         break;
984         
985     }
986 }
987
988 static long keyed_stream_compat_ioctl_user(struct file * filp, unsigned int ioctl, unsigned long arg)
989 {
990         return keyed_stream_ioctl_user(NULL, filp, ioctl, arg);
991 }
992
993 static int keyed_stream_release_user(struct inode *inode, struct file *filp)
994 {
995     struct user_keyed_stream *s = filp->private_data;
996     unsigned long f1,f2;
997
998     spin_lock_irqsave(&(user_streams->lock),f1);
999     spin_lock_irqsave(&(s->lock), f2);
1000
1001     list_del(&(s->node));
1002
1003     spin_unlock_irqrestore(&(s->lock), f2);
1004     spin_unlock_irqrestore(&(user_streams->lock), f1);
1005     
1006     kfree(s->url);
1007     kfree(s);
1008
1009     return 0;
1010 }
1011
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,
1016 #endif
1017     .ioctl = keyed_stream_ioctl_user,
1018     .release = keyed_stream_release_user,
1019 };
1020
1021
1022 /*
1023   user_keyed_streams are allocated on user connect, and deallocated on user release
1024   
1025   palacios-side opens and closes only manipulate the open type
1026 */
1027
1028 int keyed_stream_connect_user(struct v3_guest *guest, unsigned int cmd, unsigned long arg, void *priv_data)
1029 {
1030     int fd;
1031     unsigned long flags;
1032     char *url;
1033     uint64_t len;
1034     struct user_keyed_stream *s;
1035     
1036     if (!user_streams) { 
1037         printk("palacios: no user space keyed streams!\n");
1038         return -1;
1039     }
1040
1041     // get the url
1042     if (copy_from_user(&len,(void __user *)arg,sizeof(len))) { 
1043         printk("palacios: cannot copy url len from user\n");
1044         return -1;
1045     }
1046
1047     url = kmalloc(len,GFP_KERNEL);
1048     
1049     if (!url) { 
1050         printk("palacios: cannot allocate url for user keyed stream\n");
1051         return -1;
1052     }
1053
1054     if (copy_from_user(url,((void __user *)arg)+sizeof(len),len)) {
1055         printk("palacios: cannot copy url from user\n");
1056         return -1;
1057     }
1058     url[len-1]=0;
1059         
1060     
1061     // Check for duplicate handler
1062     spin_lock_irqsave(&(user_streams->lock), flags);
1063     list_for_each_entry(s, &(user_streams->streams), node) {
1064         if (!strncasecmp(url, s->url, len)) {
1065             printk("palacios: user keyed stream connection with url \"%s\" already exists\n", url);
1066             kfree(url);
1067             return -1;
1068         }
1069     }
1070     spin_unlock_irqrestore(&(user_streams->lock), flags);
1071     
1072     // Create connection
1073     s = kmalloc(sizeof(struct user_keyed_stream), GFP_KERNEL);
1074     
1075     if (!s) {
1076         printk("palacios: cannot allocate new user keyed stream for %s\n",url);
1077         kfree(url);
1078         return -1;
1079     }
1080     
1081     
1082     // Get file descriptor
1083     fd = anon_inode_getfd("v3-kstream", &user_keyed_stream_fops, s, 0);
1084
1085     if (fd < 0) {
1086         printk("palacios: cannot allocate file descriptor for new user keyed stream for %s\n",url);
1087         kfree(s);
1088         kfree(url);
1089         return -1;
1090     }
1091     
1092     memset(s, 0, sizeof(struct user_keyed_stream));
1093     
1094     s->stype=STREAM_USER;
1095     s->url=url;
1096     
1097     init_waitqueue_head(&(s->user_wait_queue));
1098     init_waitqueue_head(&(s->host_wait_queue));
1099     
1100     // Insert connection into list
1101     spin_lock_irqsave(&(user_streams->lock), flags);
1102     list_add(&(s->node), &(user_streams->streams));
1103     spin_unlock_irqrestore(&(user_streams->lock), flags);
1104     
1105     return fd;
1106 }
1107     
1108 static struct user_keyed_stream *keyed_stream_user_find(char *url)
1109 {
1110     unsigned long flags;
1111     struct user_keyed_stream *s;
1112     
1113     if (!user_streams) { 
1114         printk("palacios: no user space keyed streams available\n");
1115         return NULL;
1116     }
1117     
1118     spin_lock_irqsave(&(user_streams->lock), flags);
1119     list_for_each_entry(s, &(user_streams->streams), node) {
1120         if (!strcasecmp(url, s->url)) {
1121             spin_unlock_irqrestore(&(user_streams->lock), flags);
1122             return s;
1123         }
1124     }
1125     
1126     spin_unlock_irqrestore(&(user_streams->lock), flags);
1127     
1128     return NULL;
1129 }
1130     
1131     
1132 static v3_keyed_stream_t open_stream_user(char *url, v3_keyed_stream_open_t ot)
1133 {
1134     unsigned long flags;
1135     struct user_keyed_stream *s;
1136     
1137     s = keyed_stream_user_find(url);
1138     
1139     if (!s) {
1140         printk("palacios: cannot open user stream %s as it does not exist yet\n",url);
1141         return NULL;
1142     }
1143
1144     spin_lock_irqsave(&(s->lock), flags);
1145
1146     if (s->waiting) {
1147         spin_unlock_irqrestore(&(s->lock), flags);
1148         printk("palacios: cannot open user stream %s as it is already in waiting state\n",url);
1149         return NULL;
1150     }
1151     
1152     s->otype = ot==V3_KS_WR_ONLY_CREATE ? V3_KS_WR_ONLY : ot;
1153     
1154     spin_unlock_irqrestore(&(s->lock), flags);
1155     
1156     return s;
1157     
1158 }
1159     
1160 // close stream does not do anything.  Creation of the stream and its cleanup
1161 // are driven by the user side, not the palacios side
1162 // might eventually want to reference count this, though
1163 static void close_stream_user(v3_keyed_stream_t stream)
1164 {
1165     return;
1166 }
1167
1168 static void preallocate_hint_key_user(v3_keyed_stream_t stream,
1169                                       char *key,
1170                                       uint64_t size)
1171 {
1172     return;
1173 }
1174
1175
1176
1177
1178 static v3_keyed_stream_key_t open_key_user(v3_keyed_stream_t stream, char *key)
1179 {
1180     unsigned long flags;
1181     struct user_keyed_stream *s = (struct user_keyed_stream *) stream;
1182     uint64_t   len = strlen(key)+1;
1183     void *user_key;
1184
1185     spin_lock_irqsave(&(s->lock), flags);
1186
1187
1188     if (resize_op(&(s->op),len)) {
1189         spin_unlock_irqrestore(&(s->lock),flags);
1190         printk("palacios: cannot resize op in opening key %s on user keyed stream %s\n",key,s->url);
1191         return NULL;
1192     }
1193
1194     s->op->type = PALACIOS_KSTREAM_OPEN_KEY;
1195     s->op->buf_len = len;
1196     strncpy(s->op->buf,key,len);
1197
1198     // enter with it locked
1199     if (do_request_to_response(s,&flags)) { 
1200         spin_unlock_irqrestore(&(s->lock),flags);
1201         printk("palacios: request/response handling failed\n");
1202         return NULL;
1203     }
1204     // return with it locked
1205
1206     user_key=s->op->user_key;
1207
1208     spin_unlock_irqrestore(&(s->lock),flags);
1209
1210     return user_key;
1211 }
1212
1213 static void close_key_user(v3_keyed_stream_t stream, v3_keyed_stream_key_t key)
1214 {
1215     struct user_keyed_stream *s = (struct user_keyed_stream *) stream;
1216     uint64_t   len = 0;
1217     unsigned long flags;
1218     
1219     spin_lock_irqsave(&(s->lock), flags);
1220
1221     if (resize_op(&(s->op),len)) {
1222         spin_unlock_irqrestore(&(s->lock),flags);
1223         printk("palacios: cannot resize op in closing key 0x%p on user keyed stream %s\n",key,s->url);
1224         return;
1225     }
1226
1227     s->op->type = PALACIOS_KSTREAM_CLOSE_KEY;
1228     s->op->buf_len = len;
1229     s->op->user_key = key;
1230
1231     // enter with it locked
1232     if (do_request_to_response(s,&flags)) { 
1233         spin_unlock_irqrestore(&(s->lock),flags);
1234         printk("palacios: request/response handling failed\n");
1235         return;
1236     }
1237     // return with it locked
1238
1239     spin_unlock_irqrestore(&(s->lock),flags);
1240
1241     return;
1242 }
1243
1244
1245
1246 static sint64_t read_key_user(v3_keyed_stream_t stream, v3_keyed_stream_key_t key,
1247                               void *buf, sint64_t rlen)
1248 {
1249
1250     struct user_keyed_stream *s = (struct user_keyed_stream *) stream;
1251     uint64_t   len = 0 ;
1252     sint64_t   xfer;
1253     unsigned long flags;
1254
1255     spin_lock_irqsave(&(s->lock), flags);
1256
1257     if (s->otype != V3_KS_RD_ONLY) { 
1258         spin_unlock_irqrestore(&(s->lock),flags);
1259         printk("palacios: attempt to read key from stream that is not in read state on %s\n",s->url);
1260     }   
1261
1262     if (resize_op(&(s->op),len)) {
1263         spin_unlock_irqrestore(&(s->lock),flags);
1264         printk("palacios: cannot resize op in reading key 0x%p on user keyed stream %s\n",key,s->url);
1265         return -1;
1266     }
1267
1268     s->op->type = PALACIOS_KSTREAM_READ_KEY;
1269     s->op->buf_len = len ;
1270     s->op->xfer = rlen;
1271     s->op->user_key = key;
1272
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");
1277         return -1;
1278     }
1279     // return with it locked
1280
1281
1282     if (s->op->xfer>0) { 
1283         memcpy(buf,s->op->buf,s->op->xfer);
1284     }
1285
1286     xfer=s->op->xfer;
1287
1288     spin_unlock_irqrestore(&(s->lock),flags);
1289
1290     return xfer;
1291 }
1292
1293
1294 static sint64_t write_key_user(v3_keyed_stream_t stream, v3_keyed_stream_key_t key,
1295                                void *buf, sint64_t wlen)
1296 {
1297
1298     struct user_keyed_stream *s = (struct user_keyed_stream *) stream;
1299     struct palacios_user_keyed_stream_op *op;
1300     uint64_t   len = wlen ;
1301     sint64_t   xfer;
1302     unsigned long flags;
1303     
1304     spin_lock_irqsave(&(s->lock), flags);
1305
1306     if (s->otype != V3_KS_WR_ONLY) { 
1307         spin_unlock_irqrestore(&(s->lock),flags);
1308         printk("palacios: attempt to write key on stream that is not in write state on %s\n",s->url);
1309     }   
1310
1311     if (resize_op(&(s->op),len)) {
1312         spin_unlock_irqrestore(&(s->lock),flags);
1313         printk("palacios: cannot resize op in reading key 0x%p on user keyed stream %s\n",key,s->url);
1314         return -1;
1315     }
1316
1317     op = s->op;
1318
1319     s->op->type = PALACIOS_KSTREAM_WRITE_KEY;
1320     s->op->buf_len = len;
1321     s->op->xfer = wlen;
1322     s->op->user_key = key;
1323
1324     memcpy(s->op->buf,buf,wlen);
1325
1326     // enter with it locked
1327     if (do_request_to_response(s,&flags)) { 
1328         spin_unlock_irqrestore(&(s->lock),flags);
1329         printk("palacios: request/response handling failed\n");
1330         return -1;
1331     }
1332     // return with it locked
1333
1334     xfer=s->op->xfer;
1335
1336     spin_unlock_irqrestore(&(s->lock),flags);
1337
1338     return xfer;
1339 }
1340
1341
1342
1343
1344 /***************************************************************************************************
1345   Generic interface
1346 *************************************************************************************************/
1347
1348 static v3_keyed_stream_t open_stream(char *url,
1349                                      v3_keyed_stream_open_t ot)
1350 {
1351     if (!strncasecmp(url,"mem:",4)) { 
1352         return open_stream_mem(url,ot);
1353     } else if (!strncasecmp(url,"file:",5)) { 
1354         return open_stream_file(url,ot);
1355     } else if (!strncasecmp(url,"user:",5)) { 
1356         return open_stream_user(url,ot);
1357     } else {
1358         printk("palacios: unsupported type in attempt to open keyed stream \"%s\"\n",url);
1359         return 0;
1360     }
1361 }
1362
1363 static void close_stream(v3_keyed_stream_t stream)
1364 {
1365     struct generic_keyed_stream *gks = (struct generic_keyed_stream *) stream;
1366     switch (gks->stype){ 
1367         case STREAM_MEM:
1368             return close_stream_mem(stream);
1369             break;
1370         case STREAM_FILE:
1371             return close_stream_file(stream);
1372             break;
1373         case STREAM_USER:
1374             return close_stream_user(stream);
1375             break;
1376         default:
1377             printk("palacios: unknown stream type %d in close\n",gks->stype);
1378             break;
1379     }
1380 }
1381
1382 static void preallocate_hint_key(v3_keyed_stream_t stream,
1383                                  char *key,
1384                                  uint64_t size)
1385 {
1386     struct generic_keyed_stream *gks = (struct generic_keyed_stream *) stream;
1387     switch (gks->stype){ 
1388         case STREAM_MEM:
1389             preallocate_hint_key_mem(stream,key,size);
1390             break;
1391         case STREAM_FILE:
1392             preallocate_hint_key_file(stream,key,size);
1393             break;
1394         case STREAM_USER:
1395             return preallocate_hint_key_user(stream,key,size);
1396             break;
1397         default:
1398             printk("palacios: unknown stream type %d in preallocate_hint_key\n",gks->stype);
1399             break;
1400     }
1401     return;
1402 }
1403
1404
1405 static v3_keyed_stream_key_t open_key(v3_keyed_stream_t stream,
1406                                       char *key)
1407 {
1408     struct generic_keyed_stream *gks = (struct generic_keyed_stream *) stream;
1409     switch (gks->stype){ 
1410         case STREAM_MEM:
1411             return open_key_mem(stream,key);
1412             break;
1413         case STREAM_FILE:
1414             return open_key_file(stream,key);
1415             break;
1416         case STREAM_USER:
1417             return open_key_user(stream,key);
1418             break;
1419         default:
1420             printk("palacios: unknown stream type %d in open_key\n",gks->stype);
1421             break;
1422     }
1423     return 0;
1424 }
1425
1426
1427 static void close_key(v3_keyed_stream_t stream, 
1428                       v3_keyed_stream_key_t key)
1429 {
1430     struct generic_keyed_stream *gks = (struct generic_keyed_stream *) stream;
1431     switch (gks->stype){ 
1432         case STREAM_MEM:
1433             return close_key_mem(stream,key);
1434             break;
1435         case STREAM_FILE:
1436             return close_key_file(stream,key);
1437             break;
1438         case STREAM_USER:
1439             return close_key_user(stream,key);
1440             break;
1441         default:
1442             printk("palacios: unknown stream type %d in close_key\n",gks->stype);
1443             break;
1444     }
1445     // nothing to do
1446     return;
1447 }
1448
1449 static sint64_t write_key(v3_keyed_stream_t stream, 
1450                           v3_keyed_stream_key_t key,
1451                           void *buf,
1452                           sint64_t len)
1453 {
1454     struct generic_keyed_stream *gks = (struct generic_keyed_stream *) stream;
1455     switch (gks->stype){ 
1456         case STREAM_MEM:
1457             return write_key_mem(stream,key,buf,len);
1458             break;
1459         case STREAM_FILE:
1460             return write_key_file(stream,key,buf,len);
1461             break;
1462         case STREAM_USER:
1463             return write_key_user(stream,key,buf,len);
1464             break;
1465         default:
1466             printk("palacios: unknown stream type %d in write_key\n",gks->stype);
1467             return -1;
1468             break;
1469     }
1470     return -1;
1471 }
1472
1473
1474 static sint64_t read_key(v3_keyed_stream_t stream, 
1475                          v3_keyed_stream_key_t key,
1476                          void *buf,
1477                          sint64_t len)
1478 {
1479     struct generic_keyed_stream *gks = (struct generic_keyed_stream *) stream;
1480     switch (gks->stype){ 
1481         case STREAM_MEM:
1482             return read_key_mem(stream,key,buf,len);
1483             break;
1484         case STREAM_FILE:
1485             return read_key_file(stream,key,buf,len);
1486             break;
1487         case STREAM_USER:
1488             return read_key_user(stream,key,buf,len);
1489             break;
1490         default:
1491             printk("palacios: unknown stream type %d in read_key\n",gks->stype);
1492             return -1;
1493             break;
1494     }
1495     return -1;
1496 }
1497
1498
1499
1500
1501 /***************************************************************************************************
1502   Hooks to palacios and inititialization
1503 *************************************************************************************************/
1504
1505     
1506 static struct v3_keyed_stream_hooks hooks = {
1507     .open = open_stream,
1508     .close = close_stream,
1509     .preallocate_hint_key = preallocate_hint_key,
1510     .open_key = open_key,
1511     .close_key = close_key,
1512     .read_key = read_key,
1513     .write_key = write_key
1514 };
1515
1516
1517 static int init_keyed_streams( void )
1518 {
1519     mem_streams = palacios_create_htable(DEF_NUM_STREAMS,hash_func,hash_comp);
1520
1521     if (!mem_streams) { 
1522         printk("palacios: failed to allocated stream pool for in-memory streams\n");
1523         return -1;
1524     }
1525
1526     user_streams = kmalloc(sizeof(struct user_keyed_streams),GFP_KERNEL);
1527
1528     if (!user_streams) { 
1529         printk("palacios: failed to allocated list for user streams\n");
1530         return -1;
1531     }
1532
1533     INIT_LIST_HEAD(&(user_streams->streams));
1534     
1535     spin_lock_init(&(user_streams->lock));
1536
1537     V3_Init_Keyed_Streams(&hooks);
1538
1539     return 0;
1540
1541 }
1542
1543 static int deinit_keyed_streams( void )
1544 {
1545     palacios_free_htable(mem_streams,1,1);
1546
1547     kfree(user_streams);
1548
1549     printk("Deinit of Palacios Keyed Streams likely leaked memory\n");
1550
1551     return 0;
1552 }
1553
1554
1555 static int guest_init_keyed_streams(struct v3_guest * guest, void ** vm_data ) 
1556 {
1557     
1558     add_guest_ctrl(guest, V3_VM_KSTREAM_USER_CONNECT, keyed_stream_connect_user, 0);
1559     
1560     return 0;
1561 }
1562
1563
1564 static int guest_deinit_keyed_streams(struct v3_guest * guest, void * vm_data)
1565 {
1566
1567     return 0;
1568 }
1569
1570
1571
1572
1573 static struct linux_ext key_stream_ext = {
1574     .name = "KEYED_STREAM_INTERFACE",
1575     .init = init_keyed_streams,
1576     .deinit = deinit_keyed_streams,
1577     .guest_init = guest_init_keyed_streams,
1578     .guest_deinit = guest_deinit_keyed_streams, 
1579 };
1580
1581
1582 register_extension(&key_stream_ext);