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.


Added file stream functionality to keyed stream interface
[palacios.git] / linux_module / iface-keyed-stream.c
1 /*
2  * Palacios keyed stream interface
3  * (c) Peter Dinda, 2011
4  */
5
6 #include <linux/fs.h>
7 #include <linux/file.h>
8 #include <linux/uaccess.h>
9
10 #include "palacios.h"
11 #include "util-hashtable.h"
12 #include "linux-exts.h"
13
14 #define sint64_t int64_t
15 #include <interfaces/vmm_keyed_stream.h>
16
17 /*
18   This is an implementation of the Palacios keyed stream interface
19   that supports two flavors of streams:
20
21   "mem:"   Streams are stored in a hash table
22   The values for this hash table are hash tables associated with 
23   each stream.   
24
25   "file:"  Streams are stored in files.  Each high-level
26   open corresponds to a directory, while  key corresponds to
27   a distinct file in that directory. 
28
29 */
30
31 #define STREAM_GENERIC 0
32 #define STREAM_MEM     1
33 #define STREAM_FILE    2
34
35
36 /*
37   All keyed streams and streams indicate their implementation type within the first field
38  */
39 struct generic_keyed_stream {
40     int stype;
41 };
42
43 struct generic_stream {
44     int stype;
45 };
46   
47
48
49
50 /****************************************************************************************
51    Memory-based implementation  ("mem:")
52 ****************************************************************************************/
53
54 #define DEF_NUM_STREAMS 16
55 #define DEF_NUM_KEYS    128
56 #define DEF_SIZE        128
57
58 /*
59   A memory keyed stream is a pointer to the underlying hash table
60   while a memory stream contains an extensible buffer for the stream
61  */
62 struct mem_keyed_stream {
63     int stype;
64     v3_keyed_stream_open_t ot;
65     struct hashtable *ht;
66 };
67
68 struct mem_stream {
69     int       stype;
70     char     *data;
71     uint32_t  size;
72     uint32_t  data_max;
73     uint32_t  ptr;
74 };
75
76 static struct mem_stream *create_mem_stream(void)
77 {
78     struct mem_stream *m = kmalloc(sizeof(struct mem_stream),GFP_KERNEL);
79
80     if (!m) {
81         return 0;
82     }
83
84
85     m->data = kmalloc(DEF_SIZE,GFP_KERNEL);
86     
87     if (!m->data) { 
88         kfree(m);
89         return 0;
90     }
91
92     m->stype = STREAM_MEM;
93     m->size=DEF_SIZE;
94     m->ptr=0;
95     m->data_max=0;
96     
97     return m;
98 }
99
100 static void destroy_mem_stream(struct mem_stream *m)
101 {
102     if (m) {
103         if (m->data) {
104             kfree(m->data);
105         }
106         m->data=0;
107         kfree(m);
108     }
109 }
110     
111 static int expand_mem_stream(struct mem_stream *m, uint32_t new_size)
112 {
113     void *data = kmalloc(new_size,GFP_KERNEL);
114     uint32_t nc;
115
116     if (!data) { 
117         return -1;
118     }
119     
120     nc = (new_size<m->data_max) ? new_size : m->data_max;
121
122     memcpy(data,m->data,nc);
123
124     kfree(m->data);
125
126     m->data=data;
127     m->size=new_size;
128     if (m->size<m->data_max) { 
129         m->data_max=m->size;
130     }
131    
132     return 0;
133 }
134
135 static uint32_t write_mem_stream(struct mem_stream *m,
136                                  void *data,
137                                  uint32_t len)
138 {
139     if ((m->ptr + len) > m->size) { 
140         if (expand_mem_stream(m,m->ptr + len)) { 
141             return 0;
142         }
143     }
144     memcpy(m->data+m->ptr,data,len);
145     m->ptr+=len;
146     m->data_max=m->ptr;
147     
148     return len;
149
150 }
151
152 static uint32_t read_mem_stream(struct mem_stream *m,
153                                 void *data,
154                                 uint32_t len)
155 {
156     if ((m->ptr + len) > m->data_max) { 
157         return 0;
158     }
159     memcpy(data,m->data+m->ptr,len);
160     m->ptr+=len;
161     
162     return len;
163
164 }
165
166
167 static void reset_mem_stream(struct mem_stream *m)
168 {
169     m->ptr=0;
170 }
171
172
173 static inline uint_t hash_func(addr_t key)
174 {
175     return palacios_hash_buffer((uchar_t*)key,strlen((uchar_t*)key));
176 }
177
178 static inline int hash_comp(addr_t k1, addr_t k2)
179 {
180     return strcasecmp((char*)k1,(char*)k2)==0;
181 }
182
183
184 // This stores all the memory keyed streams streams
185 static struct hashtable *streams=0;
186
187
188 static v3_keyed_stream_t open_stream_mem(char *url,
189                                          v3_keyed_stream_open_t ot)
190 {
191
192     if (strncasecmp(url,"mem:",4)) { 
193         printk("Illegitimate attempt to open memory stream \"%s\"\n",url);
194         return 0;
195     }
196
197     switch (ot) { 
198         case V3_KS_RD_ONLY:
199         case V3_KS_WR_ONLY: {
200             struct mem_keyed_stream *mks = (struct mem_keyed_stream *) palacios_htable_search(streams,(addr_t)(url+4));
201             if (mks) { 
202                 mks->ot=ot;
203             }
204             return (v3_keyed_stream_t) mks;
205         }
206             break;
207
208         case V3_KS_WR_ONLY_CREATE: {
209             struct mem_keyed_stream *mks = (struct mem_keyed_stream *) palacios_htable_search(streams,(addr_t)(url+4));
210             if (!mks) { 
211                 mks = (struct mem_keyed_stream *) kmalloc(sizeof(struct mem_keyed_stream),GFP_KERNEL);
212                 if (!mks) { 
213                     printk("Cannot allocate in-memory keyed stream %s\n",url);
214                     return 0;
215                 }
216             
217                 mks->ht = (void*) palacios_create_htable(DEF_NUM_KEYS,hash_func,hash_comp);
218                 if (!mks->ht) { 
219                     kfree(mks);
220                     printk("Cannot allocate in-memory keyed stream %s\n",url);
221                     return 0;
222                 }
223                 
224                 if (!palacios_htable_insert(streams,(addr_t)(url+4),(addr_t)mks)) { 
225                     palacios_free_htable(mks->ht,1,1);
226                     kfree(mks);
227                     printk("Cannot insert in-memory keyed stream %s\n",url);
228                     return 0;
229                 }
230                 mks->stype=STREAM_MEM;
231             }
232
233             mks->ot=V3_KS_WR_ONLY;
234             
235             return mks;
236             
237         }
238             break;
239
240         default:
241             printk("unsupported open type in open_stream_mem\n");
242             break;
243     }
244     
245     return 0;
246         
247 }
248
249
250
251 static void close_stream_mem(v3_keyed_stream_t stream)
252 {
253     // nothing to do
254     return;
255 }
256
257
258 static v3_keyed_stream_key_t open_key_mem(v3_keyed_stream_t stream,
259                                           char *key)
260 {
261     struct mem_keyed_stream *mks = (struct mem_keyed_stream *) stream;
262     struct hashtable *s = mks->ht;
263
264     struct mem_stream *m;
265
266     m = (struct mem_stream *) palacios_htable_search(s,(addr_t)key);
267
268     if (!m) { 
269         m = create_mem_stream();
270         
271         if (!m) { 
272             printk("Cannot allocate mem keyed stream for key %s\n",key);
273             return 0;
274         }
275
276         if (!palacios_htable_insert(s,(addr_t)key,(addr_t)m)) {
277             printk("Cannot insert mem keyed stream for key %s\n",key);
278             destroy_mem_stream(m);
279             return 0;
280         }
281     }
282
283     reset_mem_stream(m);
284     return m;
285
286 }
287
288 static void close_key_mem(v3_keyed_stream_t stream, 
289                           v3_keyed_stream_key_t key)
290 {
291     // nothing to do
292     return;
293 }
294
295 static sint64_t write_key_mem(v3_keyed_stream_t stream, 
296                               v3_keyed_stream_key_t key,
297                               void *buf,
298                               sint64_t len)
299 {
300     struct mem_keyed_stream *mks = (struct mem_keyed_stream *) stream;
301     struct mem_stream *m = (struct mem_stream *) key;
302     uint32_t mylen;
303     uint32_t writelen;
304
305     if (mks->ot!=V3_KS_WR_ONLY) {
306         return -1;
307     }
308
309     if (len<0) { 
310         return -1;
311     }
312     
313     mylen = (uint32_t) len;
314
315     writelen=write_mem_stream(m,buf,mylen);
316
317     if (writelen!=mylen) { 
318         printk("Failed to write all data for key\n");
319         return -1;
320     } else {
321         return (sint64_t)writelen;
322     }
323 }
324
325 static sint64_t read_key_mem(v3_keyed_stream_t stream, 
326                              v3_keyed_stream_key_t key,
327                              void *buf,
328                              sint64_t len)
329 {
330     struct mem_keyed_stream *mks = (struct mem_keyed_stream *) stream;
331     struct mem_stream *m = (struct mem_stream *) key;
332     uint32_t mylen;
333     uint32_t readlen;
334     
335     if (mks->ot!=V3_KS_RD_ONLY) {
336         return -1;
337     }
338
339     if (len<0) { 
340         return -1;
341     }
342     
343     mylen = (uint32_t) len;
344     
345     readlen=read_mem_stream(m,buf,mylen);
346     
347     if (readlen!=mylen) { 
348         printk("Failed to read all data for key\n");
349         return -1;
350     } else {
351         return (sint64_t)readlen;
352     }
353 }
354
355
356 /***************************************************************************************************
357   File-based implementation  ("file:")
358 *************************************************************************************************/
359
360 /*
361   A file keyed stream contains the fd of the directory
362   and a path
363 */
364
365 struct file_keyed_stream {
366     int   stype;
367     v3_keyed_stream_open_t ot;
368     char  *path;
369 };
370
371 struct file_stream {
372     int   stype;
373     struct file *f;   // the opened file
374 };
375
376
377 static int directory_ok(char *path, int flags)
378 {
379     struct file *d;
380
381     // HACK
382     return 1;
383
384     d = filp_open(path,flags,0);
385
386     if (IS_ERR(d)) { 
387         return 0;
388     } else {
389         filp_close(d,NULL);
390         return 1;
391     }
392
393 }
394
395 static v3_keyed_stream_t open_stream_file(char *url,
396                                           v3_keyed_stream_open_t ot)
397 {
398     struct file_keyed_stream *fks;
399
400     if (strncasecmp(url,"file:",5)) { 
401         printk("Illegitimate attempt to open file stream \"%s\"\n",url);
402         return 0;
403     }
404
405     fks = kmalloc(sizeof(struct file_keyed_stream),GFP_KERNEL);
406     
407     if (!fks) { 
408         printk("Cannot allocate space for file stream\n");
409         return 0;
410     }
411
412     fks->path = (char*)kmalloc(strlen(url+5)+1,GFP_KERNEL);
413     
414     if (!(fks->path)) { 
415         printk("Cannot allocate space for file stream\n");
416         kfree(fks);
417         return 0;
418     }
419     
420     strcpy(fks->path,url+5);
421     
422     fks->stype=STREAM_FILE;
423
424     //lookup starts at current->fs->root or current->fs->cwd
425
426     switch (ot) { 
427         case V3_KS_RD_ONLY:
428         case V3_KS_WR_ONLY:
429             
430             if (directory_ok(fks->path, ot==V3_KS_RD_ONLY ? O_RDONLY : O_WRONLY)) { 
431                 fks->ot=ot;
432                 return (v3_keyed_stream_t) fks;
433             } else {
434                 printk("Directory \"%s\" not found\n",fks->path);
435                 kfree(fks->path);
436                 kfree(fks);
437                 return 0;
438             }
439
440             break;
441
442         case V3_KS_WR_ONLY_CREATE: {
443            
444             if (directory_ok(fks->path, ot==V3_KS_RD_ONLY ? O_RDONLY : O_WRONLY)) { 
445                 fks->ot=V3_KS_WR_ONLY;
446                 return (v3_keyed_stream_t) fks;
447             } else {
448                 // TODO: Create Directory
449                 printk("Directory \"%s\" not found and will not be created\n",fks->path);
450                 kfree(fks->path);
451                 kfree(fks);
452                 return 0;
453             }
454
455         }
456             break;
457             
458         default:
459             printk("unsupported open type in open_stream_file\n");
460             break;
461     }
462     
463     return 0;
464         
465 }
466
467 static void close_stream_file(v3_keyed_stream_t stream)
468 {
469     struct file_keyed_stream *fks = (struct file_keyed_stream *) stream;
470     
471     kfree(fks->path);
472     kfree(fks);
473
474 }
475
476 static v3_keyed_stream_key_t open_key_file(v3_keyed_stream_t stream,
477                                            char *key)
478 {
479     struct file_keyed_stream *fks = (struct file_keyed_stream *) stream;
480     struct file_stream *fs;
481     char *path;
482
483     // the path is the stream's path plus the key name
484     // file:/home/foo + "regext" => "/home/foo/regext"
485     path = (char *) kmalloc(strlen(fks->path)+strlen(key)+2,GFP_KERNEL);
486     if (!path) {                                
487         printk("Cannot allocate file keyed stream for key %s\n",key);
488         return 0;
489     }
490     strcpy(path,fks->path);
491     strcat(path,"/");
492     strcat(path,key);
493     
494     fs = (struct file_stream *) kmalloc(sizeof(struct file_stream *),GFP_KERNEL);
495     
496     if (!fs) { 
497         printk("Cannot allocate file keyed stream for key %s\n",key);
498         kfree(path);
499         return 0;
500     }
501
502     fs->stype=STREAM_FILE;
503
504     fs->f = filp_open(path,O_RDWR|O_CREAT,0600);
505     
506     if (IS_ERR(fs->f)) {
507         printk("Cannot open relevent file \"%s\" for stream \"file:%s\" and key \"%s\"\n",path,fks->path,key);
508         kfree(fs);
509         kfree(path);
510         return 0;
511     }
512
513     kfree(path);
514
515     return fs;
516 }
517
518
519 static void close_key_file(v3_keyed_stream_t stream, 
520                            v3_keyed_stream_key_t key)
521 {
522     struct file_stream *fs = (struct file_stream *) key;
523
524     filp_close(fs->f,NULL);
525
526     kfree(fs);
527 }
528
529 static sint64_t write_key_file(v3_keyed_stream_t stream, 
530                                v3_keyed_stream_key_t key,
531                                void *buf,
532                                sint64_t len)
533 {
534     struct file_keyed_stream *fks = (struct file_keyed_stream *) stream;
535     struct file_stream *fs = (struct file_stream *) key;
536     mm_segment_t old_fs;
537     ssize_t done, left, total;
538     
539     if (fks->ot!=V3_KS_WR_ONLY) { 
540         return -1;
541     }
542     
543     if (len<0) { 
544         return -1;
545     }
546
547     total=len;
548     left=len;
549
550     old_fs = get_fs();
551     set_fs(get_ds());
552
553     while (left>0) {
554         done = fs->f->f_op->write(fs->f, buf+(total-left), left, &(fs->f->f_pos));
555         if (done<=0) {
556             return -1;
557         } else {
558             left -= done;
559         }
560     }
561     set_fs(old_fs);
562
563     return len;
564 }
565
566
567
568 static sint64_t read_key_file(v3_keyed_stream_t stream, 
569                               v3_keyed_stream_key_t key,
570                               void *buf,
571                               sint64_t len)
572 {
573     struct file_keyed_stream *fks = (struct file_keyed_stream *) stream;
574     struct file_stream *fs = (struct file_stream *) key;
575     mm_segment_t old_fs;
576     ssize_t done, left, total;
577     
578     if (fks->ot!=V3_KS_RD_ONLY) { 
579         return -1;
580     }
581
582     if (len<0) { 
583         return -1;
584     }
585
586     total=len;
587     left=len;
588
589     old_fs = get_fs();
590     set_fs(get_ds());
591
592     while (left>0) {
593         done = fs->f->f_op->read(fs->f, buf+(total-left), left, &(fs->f->f_pos));
594         if (done<=0) {
595             return -1;
596         } else {
597             left -= done;
598         }
599     }
600     set_fs(old_fs);
601
602     return len;
603
604 }
605
606
607
608
609 /***************************************************************************************************
610   Generic interface
611 *************************************************************************************************/
612
613 static v3_keyed_stream_t open_stream(char *url,
614                                      v3_keyed_stream_open_t ot)
615 {
616     if (!strncasecmp(url,"mem:",4)) { 
617         return open_stream_mem(url,ot);
618     } else if (!strncasecmp(url,"file:",5)) { 
619         return open_stream_file(url,ot);
620     } else {
621         printk("Unsupported type in attempt to open keyed stream \"%s\"\n",url);
622         return 0;
623     }
624 }
625
626 static void close_stream(v3_keyed_stream_t stream)
627 {
628     struct generic_keyed_stream *gks = (struct generic_keyed_stream *) stream;
629     switch (gks->stype){ 
630         case STREAM_MEM:
631             return close_stream_mem(stream);
632             break;
633         case STREAM_FILE:
634             return close_stream_file(stream);
635             break;
636         default:
637             printk("unknown stream type %d in close\n",gks->stype);
638             break;
639     }
640 }
641
642 static v3_keyed_stream_key_t open_key(v3_keyed_stream_t stream,
643                                       char *key)
644 {
645     struct generic_keyed_stream *gks = (struct generic_keyed_stream *) stream;
646     switch (gks->stype){ 
647         case STREAM_MEM:
648             return open_key_mem(stream,key);
649             break;
650         case STREAM_FILE:
651             return open_key_file(stream,key);
652             break;
653         default:
654             printk("unknown stream type %d in open_key\n",gks->stype);
655             break;
656     }
657     return 0;
658 }
659
660
661 static void close_key(v3_keyed_stream_t stream, 
662                       v3_keyed_stream_key_t key)
663 {
664     struct generic_keyed_stream *gks = (struct generic_keyed_stream *) stream;
665     switch (gks->stype){ 
666         case STREAM_MEM:
667             return close_key_mem(stream,key);
668             break;
669         case STREAM_FILE:
670             return close_key_file(stream,key);
671             break;
672         default:
673             printk("unknown stream type %d in close_key\n",gks->stype);
674             break;
675     }
676     // nothing to do
677     return;
678 }
679
680 static sint64_t write_key(v3_keyed_stream_t stream, 
681                           v3_keyed_stream_key_t key,
682                           void *buf,
683                           sint64_t len)
684 {
685     struct generic_keyed_stream *gks = (struct generic_keyed_stream *) stream;
686     switch (gks->stype){ 
687         case STREAM_MEM:
688             return write_key_mem(stream,key,buf,len);
689             break;
690         case STREAM_FILE:
691             return write_key_file(stream,key,buf,len);
692             break;
693         default:
694             printk("unknown stream type %d in write_key\n",gks->stype);
695             return -1;
696             break;
697     }
698     return -1;
699 }
700
701
702 static sint64_t read_key(v3_keyed_stream_t stream, 
703                          v3_keyed_stream_key_t key,
704                          void *buf,
705                          sint64_t len)
706 {
707     struct generic_keyed_stream *gks = (struct generic_keyed_stream *) stream;
708     switch (gks->stype){ 
709         case STREAM_MEM:
710             return read_key_mem(stream,key,buf,len);
711             break;
712         case STREAM_FILE:
713             return read_key_file(stream,key,buf,len);
714             break;
715         default:
716             printk("unknown stream type %d in write_key\n",gks->stype);
717             return -1;
718             break;
719     }
720     return -1;
721 }
722
723
724
725
726 /***************************************************************************************************
727   Hooks to palacios and inititialization
728 *************************************************************************************************/
729
730     
731 static struct v3_keyed_stream_hooks hooks = {
732     .open = open_stream,
733     .close = close_stream,
734     .open_key = open_key,
735     .close_key = close_key,
736     .read_key = read_key,
737     .write_key = write_key
738 };
739
740
741 static int init_keyed_streams( void )
742 {
743     streams = palacios_create_htable(DEF_NUM_STREAMS,hash_func,hash_comp);
744
745     if (!streams) { 
746         printk("Failed to allocated stream pool for in-memory streams\n");
747         return -1;
748     }
749
750     V3_Init_Keyed_Streams(&hooks);
751
752     /*
753
754     {
755     v3_keyed_stream_t s;
756     v3_keyed_stream_key_t k;
757     uint8_t buf[256];
758     uint32_t i;
759     
760     printk("Testing memory interface\n");
761     s=open_stream("mem:/foo",V3_KS_WR_ONLY_CREATE);
762     k=open_key(s,"bar");
763     write_key(s,k,"hello",5);
764     close_key(s,k);
765     k=open_key(s,"baz");
766     write_key(s,k,"foobar",6);
767     close_key(s,k);
768     for (i=0;i<=256;i++) { 
769         buf[i]=i;
770     }
771     k=open_key(s,"goo");
772     write_key(s,k,buf,256);
773     close_key(s,k);
774     close_stream(s);
775     s=open_stream("mem:/foo",V3_KS_RD_ONLY);
776     k=open_key(s,"bar");
777     read_key(s,k,buf,5);
778     buf[5]=0;
779     printk("wrote 'hello', read '%s'\n",buf);
780     close_key(s,k);
781     k=open_key(s,"baz");
782     read_key(s,k,buf,6);
783     buf[6]=0;
784     printk("wrote 'foobar', read '%s'\n",buf);
785     close_key(s,k);
786     k=open_key(s,"goo");
787     read_key(s,k,buf,256);
788     for (i=0;i<256;i++) { 
789         printk("wrote 0x%x, read 0x%x (%s)\n",i,buf[i],i==buf[i] ? "ok" : "BAD");
790     }
791     close_key(s,k);
792     close_stream(s);
793
794     printk("Testing file interface\n");
795     s=open_stream("file:/foo",V3_KS_WR_ONLY_CREATE);
796     k=open_key(s,"bar");
797     write_key(s,k,"hello",5);
798     close_key(s,k);
799     k=open_key(s,"baz");
800     write_key(s,k,"foobar",6);
801     close_key(s,k);
802     for (i=0;i<=256;i++) { 
803         buf[i]=i;
804     }
805     k=open_key(s,"goo");
806     write_key(s,k,buf,256);
807     close_key(s,k);
808     close_stream(s);
809     s=open_stream("file:/foo",V3_KS_RD_ONLY);
810     k=open_key(s,"bar");
811     read_key(s,k,buf,5);
812     buf[5]=0;
813     printk("wrote 'hello', read '%s'\n",buf);
814     close_key(s,k);
815     k=open_key(s,"baz");
816     read_key(s,k,buf,6);
817     buf[6]=0;
818     printk("wrote 'foobar', read '%s'\n",buf);
819     close_key(s,k);
820     k=open_key(s,"goo");
821     read_key(s,k,buf,256);
822     for (i=0;i<256;i++) { 
823         printk("wrote 0x%x, read 0x%x (%s)\n",i,buf[i],i==buf[i] ? "ok" : "BAD");
824     }
825     close_key(s,k);
826     close_stream(s);
827     }
828     */
829
830     return 0;
831
832 }
833
834 static int deinit_keyed_streams( void )
835 {
836     printk("DEINIT OF PALACIOS KEYED STREAMS NOT IMPLEMENTED - WE HAVE JUST LEAKED MEMORY and/or file handles!\n");
837     return -1;
838 }
839
840
841 static struct linux_ext key_stream_ext = {
842     .name = "KEYED_STREAM_INTERFACE",
843     .init = init_keyed_streams,
844     .deinit = deinit_keyed_streams,
845     .guest_init = NULL,
846     .guest_deinit = NULL
847 };
848
849
850 register_extension(&key_stream_ext);