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.


module reorganization
[palacios.git] / linux_module / iface-keyed-stream.c
1 #include "palacios.h"
2 #include "util-hashtable.h"
3 #include "linux-exts.h"
4
5 #define sint64_t int64_t
6 #include <interfaces/vmm_keyed_stream.h>
7
8 /*
9   Streams are stored in a hash table
10   The values for this hash table are hash tables associted with 
11   each stream.   A keyed stream for a "mem:" stream is 
12   an instance of the structure given here 
13 */
14
15 #define DEF_NUM_STREAMS 16
16 #define DEF_NUM_KEYS    128
17 #define DEF_SIZE        128
18
19 struct mem_stream {
20     char     *data;
21     uint32_t  size;
22     uint32_t  data_max;
23     uint32_t  ptr;
24 };
25
26 static struct mem_stream *create_mem_stream(void)
27 {
28     struct mem_stream *m = kmalloc(sizeof(struct mem_stream),GFP_KERNEL);
29
30     if (!m) {
31         return 0;
32     }
33
34     m->data = kmalloc(DEF_SIZE,GFP_KERNEL);
35     
36     if (!m->data) { 
37         kfree(m);
38         return 0;
39     }
40
41     m->size=DEF_SIZE;
42     m->ptr=0;
43     m->data_max=0;
44     
45     return m;
46 }
47
48 static void destroy_mem_stream(struct mem_stream *m)
49 {
50     if (m) {
51         if (m->data) {
52             kfree(m->data);
53         }
54         m->data=0;
55         kfree(m);
56     }
57 }
58     
59 static int expand_mem_stream(struct mem_stream *m, uint32_t new_size)
60 {
61     void *data = kmalloc(new_size,GFP_KERNEL);
62     uint32_t nc;
63
64     if (!data) { 
65         return -1;
66     }
67     
68     nc = (new_size<m->data_max) ? new_size : m->data_max;
69
70     memcpy(data,m->data,nc);
71
72     kfree(m->data);
73
74     m->data=data;
75     m->size=new_size;
76     if (m->size<m->data_max) { 
77         m->data_max=m->size;
78     }
79    
80     return 0;
81 }
82
83 static uint32_t write_mem_stream(struct mem_stream *m,
84                                  void *data,
85                                  uint32_t len)
86 {
87     if ((m->ptr + len) > m->size) { 
88         if (expand_mem_stream(m,m->ptr + len)) { 
89             return 0;
90         }
91     }
92     memcpy(m->data+m->ptr,data,len);
93     m->ptr+=len;
94     m->data_max=m->ptr;
95     
96     return len;
97
98 }
99
100 static uint32_t read_mem_stream(struct mem_stream *m,
101                                 void *data,
102                                 uint32_t len)
103 {
104     if ((m->ptr + len) > m->data_max) { 
105         return 0;
106     }
107     memcpy(data,m->data+m->ptr,len);
108     m->ptr+=len;
109     
110     return len;
111
112 }
113
114
115 static void reset_mem_stream(struct mem_stream *m)
116 {
117     m->ptr=0;
118 }
119
120
121 static inline uint_t hash_func(addr_t key)
122 {
123     return palacios_hash_buffer((uchar_t*)key,strlen((uchar_t*)key));
124 }
125
126 static inline int hash_comp(addr_t k1, addr_t k2)
127 {
128     return strcasecmp((char*)k1,(char*)k2)==0;
129 }
130
131
132 // This stores all the streams
133 static struct hashtable *streams=0;
134
135
136 static v3_keyed_stream_t open_stream(char *url,
137                                      v3_keyed_stream_open_t ot)
138 {
139     if (strncasecmp(url,"mem:",4)) { 
140         printk("Only in-memory streams are currently supported\n");
141         return 0;
142     }
143
144     switch (ot) { 
145         case V3_KS_RD_ONLY:
146         case V3_KS_WR_ONLY:
147             return (v3_keyed_stream_t) palacios_htable_search(streams,(addr_t)(url+4));
148             break;
149         case V3_KS_WR_ONLY_CREATE: {
150             struct hashtable *s = (struct hashtable *) palacios_htable_search(streams,(addr_t)(url+4));
151
152             if (!s) { 
153                  s = palacios_create_htable(DEF_NUM_KEYS,hash_func,hash_comp);
154                  if (!s) { 
155                      printk("Cannot allocate in-memory keyed stream %s\n",url);
156                      return 0;
157                  }
158                  if (!palacios_htable_insert(streams,(addr_t)(url+4),(addr_t)s)) { 
159                      printk("Cannot insert in-memory keyed stream %s\n",url);
160                      return 0;
161                  }
162             }
163
164             return s;
165             
166         }
167
168             break;
169     }
170     
171     return 0;
172     
173 }
174
175
176 static void close_stream(v3_keyed_stream_t stream)
177 {
178     // nothing to do
179     return;
180 }
181
182 static v3_keyed_stream_key_t open_key(v3_keyed_stream_t stream,
183                                       char *key)
184 {
185     struct hashtable *s = (struct hashtable *) stream;
186
187     struct mem_stream *m;
188
189     m = (struct mem_stream *) palacios_htable_search(s,(addr_t)key);
190
191     if (!m) { 
192         m = create_mem_stream();
193         
194         if (!m) { 
195             printk("Cannot allocate keyed stream for key %s\n",key);
196             return 0;
197         }
198
199         if (!palacios_htable_insert(s,(addr_t)key,(addr_t)m)) {
200             printk("Cannot insert keyed stream for key %s\n",key);
201             destroy_mem_stream(m);
202             return 0;
203         }
204     }
205
206     reset_mem_stream(m);
207     return m;
208
209 }
210
211 static void close_key(v3_keyed_stream_t stream, 
212                       v3_keyed_stream_key_t key)
213 {
214     // nothing to do
215     return;
216 }
217
218 static sint64_t write_key(v3_keyed_stream_t stream, 
219                           v3_keyed_stream_key_t key,
220                           void *buf,
221                           sint64_t len)
222 {
223     struct mem_stream *m = (struct mem_stream *) key;
224     uint32_t mylen;
225     uint32_t writelen;
226
227     if (len<0) { 
228         return len;
229     }
230     
231     mylen = (uint32_t) len;
232
233     writelen=write_mem_stream(m,buf,mylen);
234
235     if (writelen!=mylen) { 
236         printk("Failed to write all data for key\n");
237         return -1;
238     } else {
239         return (sint64_t)writelen;
240     }
241 }
242
243 static sint64_t read_key(v3_keyed_stream_t stream, 
244                          v3_keyed_stream_key_t key,
245                          void *buf,
246                          sint64_t len)
247 {
248     struct mem_stream *m = (struct mem_stream *) key;
249     uint32_t mylen;
250     uint32_t readlen;
251     
252     if (len<0) { 
253         return len;
254     }
255     
256     mylen = (uint32_t) len;
257
258     readlen=read_mem_stream(m,buf,mylen);
259
260     if (readlen!=mylen) { 
261         printk("Failed to read all data for key\n");
262         return -1;
263     } else {
264         return (sint64_t)readlen;
265     }
266 }
267     
268 static struct v3_keyed_stream_hooks hooks = {
269     .open = open_stream,
270     .close = close_stream,
271     .open_key = open_key,
272     .close_key = close_key,
273     .read_key = read_key,
274     .write_key = write_key
275 };
276
277
278 static int init_keyed_streams( void )
279 {
280     streams = palacios_create_htable(DEF_NUM_STREAMS,hash_func,hash_comp);
281
282     if (!streams) { 
283         printk("Failed to allocated stream pool\n");
284         return -1;
285     }
286
287     V3_Init_Keyed_Streams(&hooks);
288     
289     return 0;
290
291 }
292
293 static int deinit_keyed_streams( void )
294 {
295     printk("DEINIT OF PALACIOS KEYED STREAMS NOT IMPLEMENTED - WE HAVE JUST LEAKED MEMORY!\n");
296     return -1;
297 }
298
299
300 static struct linux_ext key_stream_ext = {
301     .name = "KEYED_STREAM_INTERFACE",
302     .init = init_keyed_streams,
303     .deinit = deinit_keyed_streams,
304     .guest_init = NULL,
305     .guest_deinit = NULL
306 };
307
308
309 register_extension(&key_stream_ext);