From: Peter Dinda Date: Thu, 5 May 2011 18:10:06 +0000 (-0500) Subject: Ported keyed stream support from monolithic embedding X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=e6ad3e58b34380e4b02e4fba862efc643887078e Ported keyed stream support from monolithic embedding --- diff --git a/linux_module/palacios-keyed-stream.c b/linux_module/palacios-keyed-stream.c new file mode 100644 index 0000000..b3fbe2b --- /dev/null +++ b/linux_module/palacios-keyed-stream.c @@ -0,0 +1,297 @@ +#include "palacios.h" +#include "palacios-keyed-stream.h" +#include "palacios-hashtable.h" + +#define sint64_t int64_t +#include + +/* + Streams are stored in a hash table + The values for this hash table are hash tables associted with + each stream. A keyed stream for a "mem:" stream is + an instance of the structure given here +*/ + +#define DEF_NUM_STREAMS 16 +#define DEF_NUM_KEYS 128 +#define DEF_SIZE 128 + +struct mem_stream { + char *data; + uint32_t size; + uint32_t data_max; + uint32_t ptr; +}; + +static struct mem_stream *create_mem_stream(void) +{ + struct mem_stream *m = kmalloc(sizeof(struct mem_stream),GFP_KERNEL); + + if (!m) { + return 0; + } + + m->data = kmalloc(DEF_SIZE,GFP_KERNEL); + + if (!m->data) { + kfree(m); + return 0; + } + + m->size=DEF_SIZE; + m->ptr=0; + m->data_max=0; + + return m; +} + +static void destroy_mem_stream(struct mem_stream *m) +{ + if (m) { + if (m->data) { + kfree(m->data); + } + m->data=0; + kfree(m); + } +} + +static int expand_mem_stream(struct mem_stream *m, uint32_t new_size) +{ + void *data = kmalloc(new_size,GFP_KERNEL); + uint32_t nc; + + if (!data) { + return -1; + } + + nc = (new_sizedata_max) ? new_size : m->data_max; + + memcpy(data,m->data,nc); + + kfree(m->data); + + m->data=data; + m->size=new_size; + if (m->sizedata_max) { + m->data_max=m->size; + } + + return 0; +} + +static uint32_t write_mem_stream(struct mem_stream *m, + void *data, + uint32_t len) +{ + if ((m->ptr + len) > m->size) { + if (expand_mem_stream(m,m->ptr + len)) { + return 0; + } + } + memcpy(m->data+m->ptr,data,len); + m->ptr+=len; + m->data_max=m->ptr; + + return len; + +} + +static uint32_t read_mem_stream(struct mem_stream *m, + void *data, + uint32_t len) +{ + if ((m->ptr + len) > m->data_max) { + return 0; + } + memcpy(data,m->data+m->ptr,len); + m->ptr+=len; + + return len; + +} + + +static void reset_mem_stream(struct mem_stream *m) +{ + m->ptr=0; +} + + +static inline uint_t hash_func(addr_t key) +{ + return palacios_hash_buffer((uchar_t*)key,strlen((uchar_t*)key)); +} + +static inline int hash_comp(addr_t k1, addr_t k2) +{ + return strcasecmp((char*)k1,(char*)k2)==0; +} + + +// This stores all the streams +static struct hashtable *streams=0; + + +static v3_keyed_stream_t open_stream(char *url, + v3_keyed_stream_open_t ot) +{ + if (strncasecmp(url,"mem:",4)) { + printk("Only in-memory streams are currently supported\n"); + return 0; + } + + switch (ot) { + case V3_KS_RD_ONLY: + case V3_KS_WR_ONLY: + return (v3_keyed_stream_t) palacios_htable_search(streams,(addr_t)(url+4)); + break; + case V3_KS_WR_ONLY_CREATE: { + struct hashtable *s = (struct hashtable *) palacios_htable_search(streams,(addr_t)(url+4)); + + if (!s) { + s = palacios_create_htable(DEF_NUM_KEYS,hash_func,hash_comp); + if (!s) { + printk("Cannot allocate in-memory keyed stream %s\n",url); + return 0; + } + if (!palacios_htable_insert(streams,(addr_t)(url+4),(addr_t)s)) { + printk("Cannot insert in-memory keyed stream %s\n",url); + return 0; + } + } + + return s; + + } + + break; + } + + return 0; + +} + + +static void close_stream(v3_keyed_stream_t stream) +{ + // nothing to do + return; +} + +static v3_keyed_stream_key_t open_key(v3_keyed_stream_t stream, + char *key) +{ + struct hashtable *s = (struct hashtable *) stream; + + struct mem_stream *m; + + m = (struct mem_stream *) palacios_htable_search(s,(addr_t)key); + + if (!m) { + m = create_mem_stream(); + + if (!m) { + printk("Cannot allocate keyed stream for key %s\n",key); + return 0; + } + + if (!palacios_htable_insert(s,(addr_t)key,(addr_t)m)) { + printk("Cannot insert keyed stream for key %s\n",key); + destroy_mem_stream(m); + return 0; + } + } + + reset_mem_stream(m); + return m; + +} + +static void close_key(v3_keyed_stream_t stream, + v3_keyed_stream_key_t key) +{ + // nothing to do + return; +} + +static sint64_t write_key(v3_keyed_stream_t stream, + v3_keyed_stream_key_t key, + void *buf, + sint64_t len) +{ + struct mem_stream *m = (struct mem_stream *) key; + uint32_t mylen; + uint32_t writelen; + + if (len<0) { + return len; + } + + mylen = (uint32_t) len; + + writelen=write_mem_stream(m,buf,mylen); + + if (writelen!=mylen) { + printk("Failed to write all data for key\n"); + return -1; + } else { + return (sint64_t)writelen; + } +} + +static sint64_t read_key(v3_keyed_stream_t stream, + v3_keyed_stream_key_t key, + void *buf, + sint64_t len) +{ + struct mem_stream *m = (struct mem_stream *) key; + uint32_t mylen; + uint32_t readlen; + + if (len<0) { + return len; + } + + mylen = (uint32_t) len; + + readlen=read_mem_stream(m,buf,mylen); + + if (readlen!=mylen) { + printk("Failed to read all data for key\n"); + return -1; + } else { + return (sint64_t)readlen; + } +} + +static struct v3_keyed_stream_hooks hooks = { + .open = open_stream, + .close = close_stream, + .open_key = open_key, + .close_key = close_key, + .read_key = read_key, + .write_key = write_key +}; + + +int palacios_init_keyed_streams() +{ + streams = palacios_create_htable(DEF_NUM_STREAMS,hash_func,hash_comp); + + if (!streams) { + printk("Failed to allocated stream pool\n"); + return -1; + } + + V3_Init_Keyed_Streams(&hooks); + + return 0; + +} + +int palacios_deinit_keyed_streams() +{ + printk("DEINIT OF PALACIOS KEYED STREAMS NOT IMPLEMENTED - WE HAVE JUST LEAKED MEMORY!\n"); + return -1; +} diff --git a/linux_module/palacios-keyed-stream.h b/linux_module/palacios-keyed-stream.h new file mode 100644 index 0000000..218ed51 --- /dev/null +++ b/linux_module/palacios-keyed-stream.h @@ -0,0 +1,15 @@ +/* + * Palacios VM Keyed Stream Interface (for checkpoint/restore) + * Copyright (c) 2011 Peter Dinda + */ + +#ifndef __PALACIOS_KEYED_STREAM_H__ +#define __PALACIOS_KEYED_STREAM_H__ + + + +int palacios_init_keyed_streams(void); +int palacios_deinit_keyed_streams(void); + + +#endif