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.


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