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.


Initial integration and reimplementation of user-space interface for keyed streams
[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 // List of all of the user streams
766 //
767 static struct user_keyed_streams *user_streams;
768
769
770
771 static int resize_op(struct palacios_user_keyed_stream_op **op, uint64_t buf_len)
772 {
773     struct palacios_user_keyed_stream_op *old = *op;
774     struct palacios_user_keyed_stream_op *new;
775     
776     if (!old) {
777         new = kmalloc(sizeof(struct palacios_user_keyed_stream_op)+buf_len,GFP_ATOMIC);
778         if (!new) { 
779             return -1;
780         } else {
781             new->len=sizeof(struct palacios_user_keyed_stream_op)+buf_len;
782             new->buf_len=buf_len;
783             *op=new;
784             return 0;
785         }
786     } else {
787         if ((old->len-sizeof(struct palacios_user_keyed_stream_op)) >= buf_len) { 
788             old->buf_len=buf_len;
789             return 0;
790         } else {
791             kfree(old);
792             old=0;
793             return resize_op(op,buf_len);
794         }
795     }
796 }
797
798 //
799 // The assumption is that we enter this with the stream locked
800 // and we will return with it locked;  additionally, the op structure
801 // will be overwritten with the response
802 // 
803 static int do_request_to_response(struct user_keyed_stream *s, unsigned long *flags)
804 {
805
806     if (s->waiting) {
807         printk("palacios: user keyed stream request attempted while one is already in progress on %s\n",s->url);
808         return -1;
809     }
810
811     // we are now waiting for a response
812     s->waiting = 1;
813
814     // release the stream
815     spin_unlock_irqrestore(&(s->lock), *flags);
816
817     // wake up anyone waiting on it
818     wake_up_interruptible(&(s->user_wait_queue));
819
820     // wait for someone to give us a response
821     wait_event_interruptible(s->host_wait_queue, !(s->waiting));
822
823     // reacquire the lock for our called
824     spin_lock_irqsave(&(s->lock), *flags);
825
826     return 0;
827 }
828
829 //
830 // The assumption is that we enter this with the stream locked
831 // and we will return with it UNlocked
832 // 
833 static int do_response_to_request(struct user_keyed_stream *s, unsigned long *flags)
834 {
835     if (!(s->waiting)) {
836         printk("palacios: user keyed stream response while no request is in progress on %s\n",s->url);
837         return -1;
838     }
839
840     // we are now waiting for a request
841     s->waiting = 0;
842
843     // release the stream
844     spin_unlock_irqrestore(&(s->lock), *flags);
845
846     // wake up anyone waiting on it
847     wake_up_interruptible(&(s->host_wait_queue));
848     
849     return 0;
850 }
851
852
853
854 static unsigned int keyed_stream_poll_user(struct file *filp, poll_table *wait)
855 {
856     struct user_keyed_stream *s = (struct user_keyed_stream *) (filp->private_data);
857     unsigned long flags;
858     unsigned int mask = 0;
859     
860     if (!s) {
861         return POLLERR;
862     }
863
864     poll_wait(filp, &(s->user_wait_queue), wait);
865     
866     spin_lock_irqsave(&(s->lock), flags);
867     if (s->waiting) {
868         mask |= POLLIN | POLLRDNORM;
869     }
870     spin_unlock_irqrestore(&(s->lock), flags);
871     
872     return mask;
873 }
874
875
876 static int keyed_stream_ioctl_user(struct inode *inode, struct file *filp, unsigned int ioctl, unsigned long arg)
877 {
878     void __user *argp = (void __user *)arg;
879     unsigned long flags;
880     uint64_t size;
881     
882     struct user_keyed_stream *s = (struct user_keyed_stream *) (filp->private_data);
883     
884     switch (ioctl) {
885
886         case V3_KSTREAM_REQUEST_SIZE_IOCTL:
887             
888             // inform request size
889             
890             spin_lock_irqsave(&(s->lock), flags);
891             
892             if (!(s->waiting)) {
893                 spin_unlock_irqrestore(&(s->lock), flags);
894                 return 0;
895             }
896
897             size =  sizeof(struct palacios_user_keyed_stream_op) + s->op->buf_len;
898             
899             if (copy_to_user(argp, &size, sizeof(uint64_t))) {
900                 spin_unlock_irqrestore(&(s->lock), flags);
901                 printk("palacios: palacios user key size request failed to copy data\n");
902                 return -EFAULT;
903             }
904             
905             spin_unlock_irqrestore(&(s->lock), flags);
906             
907             return 1;
908             
909             break;
910
911         case V3_KSTREAM_REQUEST_PULL_IOCTL: 
912                 
913             // pull the request
914             
915             spin_lock_irqsave(&(s->lock), flags);
916
917             if (!(s->waiting)) {
918                 spin_unlock_irqrestore(&(s->lock), flags);
919                 printk("palacios: palacios user key pull request when not waiting\n");
920                 return 0;
921             }
922
923             size =  sizeof(struct palacios_user_keyed_stream_op) + s->op->buf_len;
924
925
926             if (copy_to_user(argp, s->op, size)) {
927                 spin_unlock_irqrestore(&(s->lock), flags);
928                 printk("palacios: palacios user key pull request failed to copy data\n");
929                 return -EFAULT;
930             }
931
932             spin_unlock_irqrestore(&(s->lock), flags);
933             
934             return 1;
935             
936          
937             break;
938
939     case V3_KSTREAM_RESPONSE_PUSH_IOCTL:
940
941         // push the response
942
943         spin_lock_irqsave(&(s->lock), flags);
944
945         if (!(s->waiting)) {
946             spin_unlock_irqrestore(&(s->lock), flags);
947             printk("palacios: palacios user key push response when not waiting\n");
948             return 0;
949         }
950         
951         if (copy_from_user(&size, argp, sizeof(uint64_t))) {
952             printk("palacios: palacios user key push response failed to copy size\n");
953             spin_unlock_irqrestore(&(s->lock), flags);
954             return -EFAULT;
955         }
956
957         if (resize_op(&(s->op),size-sizeof(struct palacios_user_keyed_stream_op))) {
958             printk("palacios: unable to resize op in user key push response\n");
959             spin_unlock_irqrestore(&(s->lock), flags);
960             return -EFAULT;
961         }
962
963         if (copy_from_user(&(s->op), argp, size)) {
964             spin_unlock_irqrestore(&(s->lock), flags);
965             return -EFAULT;
966         }
967
968         do_response_to_request(s,&flags);
969         // this will have unlocked s for us
970
971         return 1;
972
973         break;
974         
975     default:
976         printk("palacios: unknown ioctl in user keyed stream\n");
977
978         return -EFAULT;
979
980         break;
981         
982     }
983 }
984
985 static int keyed_stream_release_user(struct inode *inode, struct file *filp)
986 {
987     struct user_keyed_stream *s = filp->private_data;
988     unsigned long f1,f2;
989
990     spin_lock_irqsave(&(user_streams->lock),f1);
991     spin_lock_irqsave(&(s->lock), f2);
992
993     // FIXME Need to handle case of a pending request
994
995     list_del(&(s->node));
996
997     spin_unlock_irqrestore(&(s->lock), f2);
998     spin_unlock_irqrestore(&(user_streams->lock), f1);
999     
1000     kfree(s->url);
1001     kfree(s);
1002
1003     return 0;
1004 }
1005
1006 static struct file_operations user_keyed_stream_fops = {
1007     .poll = keyed_stream_poll_user,
1008     .ioctl = keyed_stream_ioctl_user,
1009     .release = keyed_stream_release_user,
1010 };
1011
1012
1013 /*
1014   user_keyed_streams are allocated on user connect, and deallocated on user release
1015   
1016   palacios-side opens and closes only manipulate the open type
1017 */
1018
1019 int keyed_stream_connect_user(struct v3_guest *guest, unsigned int cmd, unsigned long arg, void *priv_data)
1020 {
1021     int fd;
1022     unsigned long flags;
1023     char *url;
1024     uint64_t len;
1025     struct user_keyed_stream *s;
1026     
1027     if (!user_streams) { 
1028         printk("palacios: no user space keyed streams!\n");
1029         return -1;
1030     }
1031
1032     // get the url
1033     if (copy_from_user(&len,(void __user *)arg,sizeof(len))) { 
1034         printk("palacios: cannot copy url len from user\n");
1035         return -1;
1036     }
1037
1038     url = kmalloc(len,GFP_KERNEL);
1039     
1040     if (!url) { 
1041         printk("palacios: cannot allocate url for user keyed stream\n");
1042         return -1;
1043     }
1044
1045     if (copy_from_user(url,((void __user *)arg)+sizeof(len),len)) {
1046         printk("palacios: cannot copy url from user\n");
1047         return -1;
1048     }
1049     url[len-1]=0;
1050         
1051     
1052     // Check for duplicate handler
1053     spin_lock_irqsave(&(user_streams->lock), flags);
1054     list_for_each_entry(s, &(user_streams->streams), node) {
1055         if (!strncasecmp(url, s->url, len)) {
1056             printk("palacios: user keyed stream connection with url \"%s\" already exists\n", url);
1057             kfree(url);
1058             return -1;
1059         }
1060     }
1061     spin_unlock_irqrestore(&(user_streams->lock), flags);
1062     
1063     // Create connection
1064     s = kmalloc(sizeof(struct user_keyed_stream), GFP_KERNEL);
1065     
1066     if (!s) {
1067         printk("palacios: cannot allocate new user keyed stream for %s\n",url);
1068         kfree(url);
1069         return -1;
1070     }
1071     
1072     
1073     // Get file descriptor
1074     fd = anon_inode_getfd("v3-kstream", &user_keyed_stream_fops, s, 0);
1075
1076     if (fd < 0) {
1077         printk("palacios: cannot allocate file descriptor for new user keyed stream for %s\n",url);
1078         kfree(s);
1079         kfree(url);
1080         return -1;
1081     }
1082     
1083     memset(s, 0, sizeof(struct user_keyed_stream));
1084     
1085     s->stype=STREAM_USER;
1086     s->url=url;
1087     
1088     init_waitqueue_head(&(s->user_wait_queue));
1089     init_waitqueue_head(&(s->host_wait_queue));
1090     
1091     // Insert connection into list
1092     spin_lock_irqsave(&(user_streams->lock), flags);
1093     list_add(&(s->node), &(user_streams->streams));
1094     spin_unlock_irqrestore(&(user_streams->lock), flags);
1095     
1096     return fd;
1097 }
1098     
1099 static struct user_keyed_stream *keyed_stream_user_find(char *url)
1100 {
1101     unsigned long flags;
1102     struct user_keyed_stream *s;
1103     
1104     if (!user_streams) { 
1105         printk("palacios: no user space keyed streams available\n");
1106         return NULL;
1107     }
1108     
1109     spin_lock_irqsave(&(user_streams->lock), flags);
1110     list_for_each_entry(s, &(user_streams->streams), node) {
1111         if (!strcasecmp(url, s->url)) {
1112             spin_unlock_irqrestore(&(user_streams->lock), flags);
1113             return s;
1114         }
1115     }
1116     
1117     spin_unlock_irqrestore(&(user_streams->lock), flags);
1118     
1119     return NULL;
1120 }
1121     
1122     
1123 static v3_keyed_stream_t open_stream_user(char *url, v3_keyed_stream_open_t ot)
1124 {
1125     unsigned long flags;
1126     struct user_keyed_stream *s;
1127     
1128     s = keyed_stream_user_find(url);
1129     
1130     if (!s) {
1131         printk("palacios: cannot open user stream %s as it does not exist yet\n",url);
1132         return NULL;
1133     }
1134
1135     spin_lock_irqsave(&(s->lock), flags);
1136
1137     if (s->waiting) {
1138         spin_unlock_irqrestore(&(s->lock), flags);
1139         printk("palacios: cannot open user stream %s as it is already in waiting state\n",url);
1140         return NULL;
1141     }
1142     
1143     
1144     s->otype = ot==V3_KS_WR_ONLY_CREATE ? V3_KS_WR_ONLY : ot;
1145     
1146     spin_unlock_irqrestore(&(s->lock), flags);
1147     
1148     return s;
1149     
1150 }
1151     
1152 // close stream does not do anything.  Creation of the stream and its cleanup
1153 // are driven by the user side, not the palacios side
1154 // might eventually want to reference count this, though
1155 static void close_stream_user(v3_keyed_stream_t stream)
1156 {
1157     return;
1158 }
1159
1160 static void preallocate_hint_key_user(v3_keyed_stream_t stream,
1161                                       char *key,
1162                                       uint64_t size)
1163 {
1164     return;
1165 }
1166
1167
1168
1169
1170 static v3_keyed_stream_key_t open_key_user(v3_keyed_stream_t stream, char *key)
1171 {
1172     unsigned long flags;
1173     struct user_keyed_stream *s = (struct user_keyed_stream *) stream;
1174     struct palacios_user_keyed_stream_op *op;
1175     uint64_t   len = strlen(key)+1;
1176     void *user_key;
1177
1178     spin_lock_irqsave(&(s->lock), flags);
1179
1180     if (resize_op(&(s->op),len)) {
1181         spin_unlock_irqrestore(&(s->lock),flags);
1182         printk("palacios: cannot resize op in opening key %s on user keyed stream %s\n",key,s->url);
1183         return NULL;
1184     }
1185
1186     op = s->op;
1187
1188     op->type = PALACIOS_KSTREAM_OPEN_KEY;
1189     op->buf_len = len;
1190     strncpy(op->buf,key,len);
1191
1192     
1193     // enter with it locked
1194     if (do_request_to_response(s,&flags)) { 
1195         spin_unlock_irqrestore(&(s->lock),flags);
1196         printk("palacios: request/response handling failed\n");
1197         return NULL;
1198     }
1199     // return with it locked
1200
1201     user_key=s->op->user_key;
1202
1203     spin_unlock_irqrestore(&(s->lock),flags);
1204     
1205     return user_key;
1206 }
1207
1208 static void close_key_user(v3_keyed_stream_t stream, v3_keyed_stream_key_t key)
1209 {
1210     struct user_keyed_stream *s = (struct user_keyed_stream *) stream;
1211     struct palacios_user_keyed_stream_op *op;
1212     uint64_t   len = 0;
1213     unsigned long flags;
1214     
1215     spin_lock_irqsave(&(s->lock), flags);
1216
1217     if (resize_op(&(s->op),len)) {
1218         spin_unlock_irqrestore(&(s->lock),flags);
1219         printk("palacios: cannot resize op in closing key 0x%p on user keyed stream %s\n",key,s->url);
1220         return;
1221     }
1222
1223     op = s->op;
1224
1225     op->type = PALACIOS_KSTREAM_CLOSE_KEY;
1226     op->buf_len = len;
1227     op->user_key = key;
1228
1229     // enter with it locked
1230     if (do_request_to_response(s,&flags)) { 
1231         spin_unlock_irqrestore(&(s->lock),flags);
1232         printk("palacios: request/response handling failed\n");
1233         return;
1234     }
1235     // return with it locked
1236
1237     spin_unlock_irqrestore(&(s->lock),flags);
1238     
1239     return;
1240 }
1241
1242
1243
1244 static sint64_t read_key_user(v3_keyed_stream_t stream, v3_keyed_stream_key_t key,
1245                               void *buf, sint64_t rlen)
1246 {
1247
1248     struct user_keyed_stream *s = (struct user_keyed_stream *) stream;
1249     struct palacios_user_keyed_stream_op *op;
1250     uint64_t   len = 0 ;
1251     sint64_t   xfer;
1252     unsigned long flags;
1253
1254     spin_lock_irqsave(&(s->lock), flags);
1255
1256     if (s->otype != V3_KS_RD_ONLY) { 
1257         spin_unlock_irqrestore(&(s->lock),flags);
1258         printk("palacios: attempt to read key from stream that is not in read state on %s\n",s->url);
1259     }   
1260
1261     if (resize_op(&(s->op),len)) {
1262         spin_unlock_irqrestore(&(s->lock),flags);
1263         printk("palacios: cannot resize op in reading key 0x%p on user keyed stream %s\n",key,s->url);
1264         return -1;
1265     }
1266
1267     op = s->op;
1268
1269     op->type = PALACIOS_KSTREAM_READ_KEY;
1270     op->buf_len = len;
1271     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     if (op->xfer>0) { 
1282         memcpy(buf,op->buf,op->xfer);
1283     }
1284
1285     xfer=op->xfer;
1286
1287     spin_unlock_irqrestore(&(s->lock),flags);
1288
1289     return xfer;
1290 }
1291
1292
1293 static sint64_t write_key_user(v3_keyed_stream_t stream, v3_keyed_stream_key_t key,
1294                                void *buf, sint64_t wlen)
1295 {
1296
1297     struct user_keyed_stream *s = (struct user_keyed_stream *) stream;
1298     struct palacios_user_keyed_stream_op *op;
1299     uint64_t   len = wlen ;
1300     sint64_t   xfer;
1301     unsigned long flags;
1302     
1303     spin_lock_irqsave(&(s->lock), flags);
1304
1305     if (s->otype != V3_KS_WR_ONLY) { 
1306         spin_unlock_irqrestore(&(s->lock),flags);
1307         printk("palacios: attempt to write key on stream that is not in write state on %s\n",s->url);
1308     }   
1309
1310     if (resize_op(&(s->op),len)) {
1311         spin_unlock_irqrestore(&(s->lock),flags);
1312         printk("palacios: cannot resize op in reading key 0x%p on user keyed stream %s\n",key,s->url);
1313         return -1;
1314     }
1315
1316     op = s->op;
1317
1318     op->type = PALACIOS_KSTREAM_WRITE_KEY;
1319     op->buf_len = len;
1320     op->user_key = key;
1321
1322     memcpy(op->buf,buf,wlen);
1323
1324     // enter with it locked
1325     if (do_request_to_response(s,&flags)) { 
1326         spin_unlock_irqrestore(&(s->lock),flags);
1327         printk("palacios: request/response handling failed\n");
1328         return -1;
1329     }
1330     // return with it locked
1331
1332     xfer=op->xfer;
1333
1334     spin_unlock_irqrestore(&(s->lock),flags);
1335
1336     return xfer;
1337 }
1338
1339
1340
1341
1342 /***************************************************************************************************
1343   Generic interface
1344 *************************************************************************************************/
1345
1346 static v3_keyed_stream_t open_stream(char *url,
1347                                      v3_keyed_stream_open_t ot)
1348 {
1349     if (!strncasecmp(url,"mem:",4)) { 
1350         return open_stream_mem(url,ot);
1351     } else if (!strncasecmp(url,"file:",5)) { 
1352         return open_stream_file(url,ot);
1353     } else if (!strncasecmp(url,"user:",5)) { 
1354         return open_stream_user(url,ot);
1355     } else {
1356         printk("palacios: unsupported type in attempt to open keyed stream \"%s\"\n",url);
1357         return 0;
1358     }
1359 }
1360
1361 static void close_stream(v3_keyed_stream_t stream)
1362 {
1363     struct generic_keyed_stream *gks = (struct generic_keyed_stream *) stream;
1364     switch (gks->stype){ 
1365         case STREAM_MEM:
1366             return close_stream_mem(stream);
1367             break;
1368         case STREAM_FILE:
1369             return close_stream_file(stream);
1370             break;
1371         case STREAM_USER:
1372             return close_stream_user(stream);
1373             break;
1374         default:
1375             printk("palacios: unknown stream type %d in close\n",gks->stype);
1376             break;
1377     }
1378 }
1379
1380 static void preallocate_hint_key(v3_keyed_stream_t stream,
1381                                  char *key,
1382                                  uint64_t size)
1383 {
1384     struct generic_keyed_stream *gks = (struct generic_keyed_stream *) stream;
1385     switch (gks->stype){ 
1386         case STREAM_MEM:
1387             preallocate_hint_key_mem(stream,key,size);
1388             break;
1389         case STREAM_FILE:
1390             preallocate_hint_key_file(stream,key,size);
1391             break;
1392         case STREAM_USER:
1393             return preallocate_hint_key_user(stream,key,size);
1394             break;
1395         default:
1396             printk("palacios: unknown stream type %d in preallocate_hint_key\n",gks->stype);
1397             break;
1398     }
1399     return;
1400 }
1401
1402
1403 static v3_keyed_stream_key_t open_key(v3_keyed_stream_t stream,
1404                                       char *key)
1405 {
1406     struct generic_keyed_stream *gks = (struct generic_keyed_stream *) stream;
1407     switch (gks->stype){ 
1408         case STREAM_MEM:
1409             return open_key_mem(stream,key);
1410             break;
1411         case STREAM_FILE:
1412             return open_key_file(stream,key);
1413             break;
1414         case STREAM_USER:
1415             return open_key_user(stream,key);
1416             break;
1417         default:
1418             printk("palacios: unknown stream type %d in open_key\n",gks->stype);
1419             break;
1420     }
1421     return 0;
1422 }
1423
1424
1425 static void close_key(v3_keyed_stream_t stream, 
1426                       v3_keyed_stream_key_t key)
1427 {
1428     struct generic_keyed_stream *gks = (struct generic_keyed_stream *) stream;
1429     switch (gks->stype){ 
1430         case STREAM_MEM:
1431             return close_key_mem(stream,key);
1432             break;
1433         case STREAM_FILE:
1434             return close_key_file(stream,key);
1435             break;
1436         case STREAM_USER:
1437             return close_key_user(stream,key);
1438             break;
1439         default:
1440             printk("palacios: unknown stream type %d in close_key\n",gks->stype);
1441             break;
1442     }
1443     // nothing to do
1444     return;
1445 }
1446
1447 static sint64_t write_key(v3_keyed_stream_t stream, 
1448                           v3_keyed_stream_key_t key,
1449                           void *buf,
1450                           sint64_t len)
1451 {
1452     struct generic_keyed_stream *gks = (struct generic_keyed_stream *) stream;
1453     switch (gks->stype){ 
1454         case STREAM_MEM:
1455             return write_key_mem(stream,key,buf,len);
1456             break;
1457         case STREAM_FILE:
1458             return write_key_file(stream,key,buf,len);
1459             break;
1460         case STREAM_USER:
1461             return write_key_user(stream,key,buf,len);
1462             break;
1463         default:
1464             printk("palacios: unknown stream type %d in write_key\n",gks->stype);
1465             return -1;
1466             break;
1467     }
1468     return -1;
1469 }
1470
1471
1472 static sint64_t read_key(v3_keyed_stream_t stream, 
1473                          v3_keyed_stream_key_t key,
1474                          void *buf,
1475                          sint64_t len)
1476 {
1477     struct generic_keyed_stream *gks = (struct generic_keyed_stream *) stream;
1478     switch (gks->stype){ 
1479         case STREAM_MEM:
1480             return read_key_mem(stream,key,buf,len);
1481             break;
1482         case STREAM_FILE:
1483             return read_key_file(stream,key,buf,len);
1484             break;
1485         case STREAM_USER:
1486             return read_key_user(stream,key,buf,len);
1487             break;
1488         default:
1489             printk("palacios: unknown stream type %d in read_key\n",gks->stype);
1490             return -1;
1491             break;
1492     }
1493     return -1;
1494 }
1495
1496
1497
1498
1499 /***************************************************************************************************
1500   Hooks to palacios and inititialization
1501 *************************************************************************************************/
1502
1503     
1504 static struct v3_keyed_stream_hooks hooks = {
1505     .open = open_stream,
1506     .close = close_stream,
1507     .preallocate_hint_key = preallocate_hint_key,
1508     .open_key = open_key,
1509     .close_key = close_key,
1510     .read_key = read_key,
1511     .write_key = write_key
1512 };
1513
1514
1515 static int init_keyed_streams( void )
1516 {
1517     mem_streams = palacios_create_htable(DEF_NUM_STREAMS,hash_func,hash_comp);
1518
1519     if (!mem_streams) { 
1520         printk("palacios: failed to allocated stream pool for in-memory streams\n");
1521         return -1;
1522     }
1523
1524     user_streams = kmalloc(sizeof(struct user_keyed_streams),GFP_KERNEL);
1525
1526     if (!user_streams) { 
1527         printk("palacios: failed to allocated list for user streams\n");
1528         return -1;
1529     }
1530
1531     INIT_LIST_HEAD(&(user_streams->streams));
1532     
1533     spin_lock_init(&(user_streams->lock));
1534
1535     V3_Init_Keyed_Streams(&hooks);
1536
1537     return 0;
1538
1539 }
1540
1541 static int deinit_keyed_streams( void )
1542 {
1543     palacios_free_htable(mem_streams,1,1);
1544
1545     kfree(user_streams);
1546
1547     printk("Deinit of Palacios Keyed Streams likely leaked memory\n");
1548
1549     return 0;
1550 }
1551
1552
1553 static int guest_init_keyed_streams(struct v3_guest * guest, void ** vm_data ) 
1554 {
1555     
1556     add_guest_ctrl(guest, V3_VM_KSTREAM_USER_CONNECT, keyed_stream_connect_user, 0);
1557     
1558     return 0;
1559 }
1560
1561
1562 static int guest_deinit_keyed_streams(struct v3_guest * guest, void * vm_data)
1563 {
1564
1565     return 0;
1566 }
1567
1568
1569
1570
1571 static struct linux_ext key_stream_ext = {
1572     .name = "KEYED_STREAM_INTERFACE",
1573     .init = init_keyed_streams,
1574     .deinit = deinit_keyed_streams,
1575     .guest_init = guest_init_keyed_streams,
1576     .guest_deinit = guest_deinit_keyed_streams, 
1577 };
1578
1579
1580 register_extension(&key_stream_ext);