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.


Fix compile error in keyed stream for newer linux kernels
[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 #else
1017     .ioctl = keyed_stream_ioctl_user,
1018 #endif
1019     .release = keyed_stream_release_user,
1020 };
1021
1022
1023 /*
1024   user_keyed_streams are allocated on user connect, and deallocated on user release
1025   
1026   palacios-side opens and closes only manipulate the open type
1027 */
1028
1029 int keyed_stream_connect_user(struct v3_guest *guest, unsigned int cmd, unsigned long arg, void *priv_data)
1030 {
1031     int fd;
1032     unsigned long flags;
1033     char *url;
1034     uint64_t len;
1035     struct user_keyed_stream *s;
1036     
1037     if (!user_streams) { 
1038         printk("palacios: no user space keyed streams!\n");
1039         return -1;
1040     }
1041
1042     // get the url
1043     if (copy_from_user(&len,(void __user *)arg,sizeof(len))) { 
1044         printk("palacios: cannot copy url len from user\n");
1045         return -1;
1046     }
1047
1048     url = kmalloc(len,GFP_KERNEL);
1049     
1050     if (!url) { 
1051         printk("palacios: cannot allocate url for user keyed stream\n");
1052         return -1;
1053     }
1054
1055     if (copy_from_user(url,((void __user *)arg)+sizeof(len),len)) {
1056         printk("palacios: cannot copy url from user\n");
1057         return -1;
1058     }
1059     url[len-1]=0;
1060         
1061     
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);
1067             kfree(url);
1068             return -1;
1069         }
1070     }
1071     spin_unlock_irqrestore(&(user_streams->lock), flags);
1072     
1073     // Create connection
1074     s = kmalloc(sizeof(struct user_keyed_stream), GFP_KERNEL);
1075     
1076     if (!s) {
1077         printk("palacios: cannot allocate new user keyed stream for %s\n",url);
1078         kfree(url);
1079         return -1;
1080     }
1081     
1082     
1083     // Get file descriptor
1084     fd = anon_inode_getfd("v3-kstream", &user_keyed_stream_fops, s, 0);
1085
1086     if (fd < 0) {
1087         printk("palacios: cannot allocate file descriptor for new user keyed stream for %s\n",url);
1088         kfree(s);
1089         kfree(url);
1090         return -1;
1091     }
1092     
1093     memset(s, 0, sizeof(struct user_keyed_stream));
1094     
1095     s->stype=STREAM_USER;
1096     s->url=url;
1097     
1098     init_waitqueue_head(&(s->user_wait_queue));
1099     init_waitqueue_head(&(s->host_wait_queue));
1100     
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);
1105     
1106     return fd;
1107 }
1108     
1109 static struct user_keyed_stream *keyed_stream_user_find(char *url)
1110 {
1111     unsigned long flags;
1112     struct user_keyed_stream *s;
1113     
1114     if (!user_streams) { 
1115         printk("palacios: no user space keyed streams available\n");
1116         return NULL;
1117     }
1118     
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);
1123             return s;
1124         }
1125     }
1126     
1127     spin_unlock_irqrestore(&(user_streams->lock), flags);
1128     
1129     return NULL;
1130 }
1131     
1132     
1133 static v3_keyed_stream_t open_stream_user(char *url, v3_keyed_stream_open_t ot)
1134 {
1135     unsigned long flags;
1136     struct user_keyed_stream *s;
1137     
1138     s = keyed_stream_user_find(url);
1139     
1140     if (!s) {
1141         printk("palacios: cannot open user stream %s as it does not exist yet\n",url);
1142         return NULL;
1143     }
1144
1145     spin_lock_irqsave(&(s->lock), flags);
1146
1147     if (s->waiting) {
1148         spin_unlock_irqrestore(&(s->lock), flags);
1149         printk("palacios: cannot open user stream %s as it is already in waiting state\n",url);
1150         return NULL;
1151     }
1152     
1153     s->otype = ot==V3_KS_WR_ONLY_CREATE ? V3_KS_WR_ONLY : ot;
1154     
1155     spin_unlock_irqrestore(&(s->lock), flags);
1156     
1157     return s;
1158     
1159 }
1160     
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)
1165 {
1166     return;
1167 }
1168
1169 static void preallocate_hint_key_user(v3_keyed_stream_t stream,
1170                                       char *key,
1171                                       uint64_t size)
1172 {
1173     return;
1174 }
1175
1176
1177
1178
1179 static v3_keyed_stream_key_t open_key_user(v3_keyed_stream_t stream, char *key)
1180 {
1181     unsigned long flags;
1182     struct user_keyed_stream *s = (struct user_keyed_stream *) stream;
1183     uint64_t   len = strlen(key)+1;
1184     void *user_key;
1185
1186     spin_lock_irqsave(&(s->lock), flags);
1187
1188
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);
1192         return NULL;
1193     }
1194
1195     s->op->type = PALACIOS_KSTREAM_OPEN_KEY;
1196     s->op->buf_len = len;
1197     strncpy(s->op->buf,key,len);
1198
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");
1203         return NULL;
1204     }
1205     // return with it locked
1206
1207     user_key=s->op->user_key;
1208
1209     spin_unlock_irqrestore(&(s->lock),flags);
1210
1211     return user_key;
1212 }
1213
1214 static void close_key_user(v3_keyed_stream_t stream, v3_keyed_stream_key_t key)
1215 {
1216     struct user_keyed_stream *s = (struct user_keyed_stream *) stream;
1217     uint64_t   len = 0;
1218     unsigned long flags;
1219     
1220     spin_lock_irqsave(&(s->lock), flags);
1221
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);
1225         return;
1226     }
1227
1228     s->op->type = PALACIOS_KSTREAM_CLOSE_KEY;
1229     s->op->buf_len = len;
1230     s->op->user_key = key;
1231
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");
1236         return;
1237     }
1238     // return with it locked
1239
1240     spin_unlock_irqrestore(&(s->lock),flags);
1241
1242     return;
1243 }
1244
1245
1246
1247 static sint64_t read_key_user(v3_keyed_stream_t stream, v3_keyed_stream_key_t key,
1248                               void *buf, sint64_t rlen)
1249 {
1250
1251     struct user_keyed_stream *s = (struct user_keyed_stream *) stream;
1252     uint64_t   len = 0 ;
1253     sint64_t   xfer;
1254     unsigned long flags;
1255
1256     spin_lock_irqsave(&(s->lock), flags);
1257
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);
1261     }   
1262
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);
1266         return -1;
1267     }
1268
1269     s->op->type = PALACIOS_KSTREAM_READ_KEY;
1270     s->op->buf_len = len ;
1271     s->op->xfer = rlen;
1272     s->op->user_key = key;
1273
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");
1278         return -1;
1279     }
1280     // return with it locked
1281
1282
1283     if (s->op->xfer>0) { 
1284         memcpy(buf,s->op->buf,s->op->xfer);
1285     }
1286
1287     xfer=s->op->xfer;
1288
1289     spin_unlock_irqrestore(&(s->lock),flags);
1290
1291     return xfer;
1292 }
1293
1294
1295 static sint64_t write_key_user(v3_keyed_stream_t stream, v3_keyed_stream_key_t key,
1296                                void *buf, sint64_t wlen)
1297 {
1298
1299     struct user_keyed_stream *s = (struct user_keyed_stream *) stream;
1300     struct palacios_user_keyed_stream_op *op;
1301     uint64_t   len = wlen ;
1302     sint64_t   xfer;
1303     unsigned long flags;
1304     
1305     spin_lock_irqsave(&(s->lock), flags);
1306
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);
1310     }   
1311
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);
1315         return -1;
1316     }
1317
1318     op = s->op;
1319
1320     s->op->type = PALACIOS_KSTREAM_WRITE_KEY;
1321     s->op->buf_len = len;
1322     s->op->xfer = wlen;
1323     s->op->user_key = key;
1324
1325     memcpy(s->op->buf,buf,wlen);
1326
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");
1331         return -1;
1332     }
1333     // return with it locked
1334
1335     xfer=s->op->xfer;
1336
1337     spin_unlock_irqrestore(&(s->lock),flags);
1338
1339     return xfer;
1340 }
1341
1342
1343
1344
1345 /***************************************************************************************************
1346   Generic interface
1347 *************************************************************************************************/
1348
1349 static v3_keyed_stream_t open_stream(char *url,
1350                                      v3_keyed_stream_open_t ot)
1351 {
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);
1358     } else {
1359         printk("palacios: unsupported type in attempt to open keyed stream \"%s\"\n",url);
1360         return 0;
1361     }
1362 }
1363
1364 static void close_stream(v3_keyed_stream_t stream)
1365 {
1366     struct generic_keyed_stream *gks = (struct generic_keyed_stream *) stream;
1367     switch (gks->stype){ 
1368         case STREAM_MEM:
1369             return close_stream_mem(stream);
1370             break;
1371         case STREAM_FILE:
1372             return close_stream_file(stream);
1373             break;
1374         case STREAM_USER:
1375             return close_stream_user(stream);
1376             break;
1377         default:
1378             printk("palacios: unknown stream type %d in close\n",gks->stype);
1379             break;
1380     }
1381 }
1382
1383 static void preallocate_hint_key(v3_keyed_stream_t stream,
1384                                  char *key,
1385                                  uint64_t size)
1386 {
1387     struct generic_keyed_stream *gks = (struct generic_keyed_stream *) stream;
1388     switch (gks->stype){ 
1389         case STREAM_MEM:
1390             preallocate_hint_key_mem(stream,key,size);
1391             break;
1392         case STREAM_FILE:
1393             preallocate_hint_key_file(stream,key,size);
1394             break;
1395         case STREAM_USER:
1396             return preallocate_hint_key_user(stream,key,size);
1397             break;
1398         default:
1399             printk("palacios: unknown stream type %d in preallocate_hint_key\n",gks->stype);
1400             break;
1401     }
1402     return;
1403 }
1404
1405
1406 static v3_keyed_stream_key_t open_key(v3_keyed_stream_t stream,
1407                                       char *key)
1408 {
1409     struct generic_keyed_stream *gks = (struct generic_keyed_stream *) stream;
1410     switch (gks->stype){ 
1411         case STREAM_MEM:
1412             return open_key_mem(stream,key);
1413             break;
1414         case STREAM_FILE:
1415             return open_key_file(stream,key);
1416             break;
1417         case STREAM_USER:
1418             return open_key_user(stream,key);
1419             break;
1420         default:
1421             printk("palacios: unknown stream type %d in open_key\n",gks->stype);
1422             break;
1423     }
1424     return 0;
1425 }
1426
1427
1428 static void close_key(v3_keyed_stream_t stream, 
1429                       v3_keyed_stream_key_t key)
1430 {
1431     struct generic_keyed_stream *gks = (struct generic_keyed_stream *) stream;
1432     switch (gks->stype){ 
1433         case STREAM_MEM:
1434             return close_key_mem(stream,key);
1435             break;
1436         case STREAM_FILE:
1437             return close_key_file(stream,key);
1438             break;
1439         case STREAM_USER:
1440             return close_key_user(stream,key);
1441             break;
1442         default:
1443             printk("palacios: unknown stream type %d in close_key\n",gks->stype);
1444             break;
1445     }
1446     // nothing to do
1447     return;
1448 }
1449
1450 static sint64_t write_key(v3_keyed_stream_t stream, 
1451                           v3_keyed_stream_key_t key,
1452                           void *buf,
1453                           sint64_t len)
1454 {
1455     struct generic_keyed_stream *gks = (struct generic_keyed_stream *) stream;
1456     switch (gks->stype){ 
1457         case STREAM_MEM:
1458             return write_key_mem(stream,key,buf,len);
1459             break;
1460         case STREAM_FILE:
1461             return write_key_file(stream,key,buf,len);
1462             break;
1463         case STREAM_USER:
1464             return write_key_user(stream,key,buf,len);
1465             break;
1466         default:
1467             printk("palacios: unknown stream type %d in write_key\n",gks->stype);
1468             return -1;
1469             break;
1470     }
1471     return -1;
1472 }
1473
1474
1475 static sint64_t read_key(v3_keyed_stream_t stream, 
1476                          v3_keyed_stream_key_t key,
1477                          void *buf,
1478                          sint64_t len)
1479 {
1480     struct generic_keyed_stream *gks = (struct generic_keyed_stream *) stream;
1481     switch (gks->stype){ 
1482         case STREAM_MEM:
1483             return read_key_mem(stream,key,buf,len);
1484             break;
1485         case STREAM_FILE:
1486             return read_key_file(stream,key,buf,len);
1487             break;
1488         case STREAM_USER:
1489             return read_key_user(stream,key,buf,len);
1490             break;
1491         default:
1492             printk("palacios: unknown stream type %d in read_key\n",gks->stype);
1493             return -1;
1494             break;
1495     }
1496     return -1;
1497 }
1498
1499
1500
1501
1502 /***************************************************************************************************
1503   Hooks to palacios and inititialization
1504 *************************************************************************************************/
1505
1506     
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
1515 };
1516
1517
1518 static int init_keyed_streams( void )
1519 {
1520     mem_streams = palacios_create_htable(DEF_NUM_STREAMS,hash_func,hash_comp);
1521
1522     if (!mem_streams) { 
1523         printk("palacios: failed to allocated stream pool for in-memory streams\n");
1524         return -1;
1525     }
1526
1527     user_streams = kmalloc(sizeof(struct user_keyed_streams),GFP_KERNEL);
1528
1529     if (!user_streams) { 
1530         printk("palacios: failed to allocated list for user streams\n");
1531         return -1;
1532     }
1533
1534     INIT_LIST_HEAD(&(user_streams->streams));
1535     
1536     spin_lock_init(&(user_streams->lock));
1537
1538     V3_Init_Keyed_Streams(&hooks);
1539
1540     return 0;
1541
1542 }
1543
1544 static int deinit_keyed_streams( void )
1545 {
1546     palacios_free_htable(mem_streams,1,1);
1547
1548     kfree(user_streams);
1549
1550     printk("Deinit of Palacios Keyed Streams likely leaked memory\n");
1551
1552     return 0;
1553 }
1554
1555
1556 static int guest_init_keyed_streams(struct v3_guest * guest, void ** vm_data ) 
1557 {
1558     
1559     add_guest_ctrl(guest, V3_VM_KSTREAM_USER_CONNECT, keyed_stream_connect_user, 0);
1560     
1561     return 0;
1562 }
1563
1564
1565 static int guest_deinit_keyed_streams(struct v3_guest * guest, void * vm_data)
1566 {
1567
1568     return 0;
1569 }
1570
1571
1572
1573
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, 
1580 };
1581
1582
1583 register_extension(&key_stream_ext);