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.


interface updates
[palacios.git] / linux_module / iface-stream.c
1
2 /* 
3  * VM specific Controls
4  * (c) Lei Xia, 2010
5  */
6 #include <linux/errno.h>
7 #include <linux/percpu.h>
8 #include <linux/sched.h>
9 #include <linux/uaccess.h>
10
11
12 #include <interfaces/vmm_stream.h>
13 #include "linux-exts.h"
14 #include "util-ringbuffer.h"
15 #include "vm.h"
16 #include "iface-stream.h"
17
18 #define STREAM_BUF_SIZE 1024
19
20
21
22
23 static struct list_head global_streams;
24
25 struct stream_buffer {
26     char name[STREAM_NAME_LEN];
27     struct ringbuf * buf;
28
29     wait_queue_head_t intr_queue;
30     spinlock_t lock;
31
32     struct v3_guest * guest;
33     struct list_head stream_node;
34 };
35
36
37 // Currently just the list of open streams
38 struct vm_stream_state {
39     struct list_head open_streams;
40 };
41
42 static int stream_enqueue(struct stream_buffer * stream, char * buf, int len) {
43     int bytes = 0;
44
45     bytes = ringbuf_write(stream->buf, buf, len);
46
47     return bytes;
48 }
49
50
51 static int stream_dequeue(struct stream_buffer * stream, char * buf, int len) {
52     int bytes = 0;
53
54     bytes = ringbuf_read(stream->buf, buf, len);
55
56     return bytes;
57 }
58
59 static int stream_datalen(struct stream_buffer * stream){
60     return ringbuf_data_len(stream->buf);
61 }
62
63
64
65
66
67 static struct stream_buffer * find_stream_by_name(struct v3_guest * guest, const char * name) {
68     struct stream_buffer * stream = NULL;
69     struct list_head * stream_list = NULL;
70     struct vm_stream_state * vm_state = NULL;
71
72
73     if (guest == NULL) {
74         stream_list = &global_streams;
75     } else {
76         vm_state = get_vm_ext_data(guest, "STREAM_INTERFACE");
77
78         if (vm_state == NULL) {
79             printk("ERROR: Could not locate vm stream state for extension STREAM_INTERFACE\n");
80             return NULL;
81         }
82
83         stream_list = &(vm_state->open_streams);
84     }
85
86     list_for_each_entry(stream,  stream_list, stream_node) {
87         if (strncmp(stream->name, name, STREAM_NAME_LEN) == 0) {
88             return stream;
89         }
90     }
91
92     return NULL;
93 }
94
95
96 static void * palacios_stream_open(const char * name, void * private_data) {
97     struct v3_guest * guest = (struct v3_guest *)private_data;
98     struct stream_buffer * stream = NULL;
99     struct vm_stream_state * vm_state = NULL;
100
101     if (guest != NULL) {
102         vm_state = get_vm_ext_data(guest, "STREAM_INTERFACE");
103
104         if (vm_state == NULL) {
105             printk("ERROR: Could not locate vm stream state for extension STREAM_INTERFACE\n");
106             return NULL;
107         }
108     }
109
110     if (find_stream_by_name(guest, name) != NULL) {
111         printk("Stream already exists\n");
112         return NULL;
113     }
114
115     stream = kmalloc(sizeof(struct stream_buffer), GFP_KERNEL);
116         
117     stream->buf = create_ringbuf(STREAM_BUF_SIZE);
118     stream->guest = guest;
119
120     strncpy(stream->name, name, STREAM_NAME_LEN - 1);
121
122     init_waitqueue_head(&(stream->intr_queue));
123     spin_lock_init(&(stream->lock));
124
125     if (guest == NULL) {
126         list_add(&(stream->stream_node), &(global_streams));
127     } else {
128         list_add(&(stream->stream_node), &(vm_state->open_streams));
129     } 
130
131     return stream;
132 }
133
134
135 static int palacios_stream_write(void * stream_ptr, char * buf, int len) {
136     struct stream_buffer * stream = (struct stream_buffer *)stream_ptr;
137     int ret = 0;
138
139     ret = stream_enqueue(stream, buf, len);
140
141     if (ret > 0) {
142         wake_up_interruptible(&(stream->intr_queue));
143     }
144
145     return ret;
146 }
147
148
149 static void palacios_stream_close(void * stream_ptr) {
150     struct stream_buffer * stream = (struct stream_buffer *)stream_ptr;
151
152     free_ringbuf(stream->buf);
153     list_del(&(stream->stream_node));
154     kfree(stream);
155
156 }
157
158 static struct v3_stream_hooks palacios_stream_hooks = {
159     .open = palacios_stream_open,
160     .write = palacios_stream_write,
161     .close = palacios_stream_close,
162 };
163
164
165 static int stream_init( void ) {
166     INIT_LIST_HEAD(&(global_streams));
167     V3_Init_Stream(&palacios_stream_hooks);
168     
169     return 0;
170 }
171
172
173 static int stream_deinit( void ) {
174     if (!list_empty(&(global_streams))) {
175         printk("Error removing module with open streams\n");
176     }
177
178     return 0;
179 }
180
181 static int stream_connect(struct v3_guest * guest, unsigned int cmd, unsigned long arg, void * priv_data) {
182     void __user * argp = (void __user *)arg;
183     char path_name[STREAM_NAME_LEN];
184     
185     if (copy_from_user(path_name, argp, STREAM_NAME_LEN)) {
186         printk("%s(%d): copy from user error...\n", __FILE__, __LINE__);
187         return -EFAULT;
188     }
189     
190
191
192     printk("ERROR: Opening Streams is currently not implemented...\n");
193
194     return -EFAULT;
195 }
196
197
198 static int guest_stream_init(struct v3_guest * guest, void ** vm_data) {
199     struct vm_stream_state * state = kmalloc(sizeof(struct vm_stream_state), GFP_KERNEL);
200
201     INIT_LIST_HEAD(&(state->open_streams));
202     *vm_data = state;
203
204
205     add_guest_ctrl(guest, V3_VM_STREAM_CONNECT, stream_connect, state);
206
207     return 0;
208 }
209
210
211 static int guest_stream_deinit(struct v3_guest * guest, void * vm_data) {
212     struct vm_stream_state * state = vm_data;
213     if (!list_empty(&(state->open_streams))) {
214         printk("Error shutting down VM with open streams\n");
215     }
216
217     return 0;
218 }
219
220
221
222 static struct linux_ext stream_ext = {
223     .name = "STREAM_INTERFACE",
224     .init = stream_init,
225     .deinit = stream_deinit,
226     .guest_init = guest_stream_init,
227     .guest_deinit = guest_stream_deinit
228 };
229
230
231 register_extension(&stream_ext);