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.


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