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.


Lock bugfixes - missing lock deinits This also adds deinit calls in the linux_module...
[palacios.git] / linux_module / iface-stream.c
index 9cb89e5..d6c6331 100644 (file)
 #include "linux-exts.h"
 #include "util-ringbuffer.h"
 #include "vm.h"
-#include "iface-stream.h"
+
 
 
 // This is probably overkill
 #define STREAM_RING_LEN 4096
-
+#define STREAM_NAME_LEN 128
 
 
 
@@ -68,7 +68,7 @@ static struct stream_state * find_stream_by_name(struct v3_guest * guest, const
        vm_state = get_vm_ext_data(guest, "STREAM_INTERFACE");
 
        if (vm_state == NULL) {
-           printk("ERROR: Could not locate vm stream state for extension STREAM_INTERFACE\n");
+           ERROR("ERROR: Could not locate vm stream state for extension STREAM_INTERFACE\n");
            return NULL;
        }
 
@@ -102,9 +102,9 @@ static ssize_t stream_read(struct file * filp, char __user * buf, size_t size, l
        int tmp_len = (TMP_BUF_LEN > bytes_left) ? bytes_left : TMP_BUF_LEN;
        int tmp_read = 0;
 
-       spin_lock_irqsave(&(stream->lock), flags);
+       palacios_spinlock_lock_irqsave(&(stream->lock), flags);
        tmp_read = ringbuf_read(stream->out_ring, tmp_buf, tmp_len);
-       spin_unlock_irqrestore(&(stream->lock), flags);
+       palacios_spinlock_unlock_irqrestore(&(stream->lock), flags);
 
        if (tmp_read == 0) {
            // If userspace reads more than we have
@@ -112,7 +112,7 @@ static ssize_t stream_read(struct file * filp, char __user * buf, size_t size, l
        }
 
        if (copy_to_user(buf + bytes_read, tmp_buf, tmp_read)) {
-           printk("Read Fault\n");
+           ERROR("Read Fault\n");
            return -EFAULT;
        }
        
@@ -121,9 +121,9 @@ static ssize_t stream_read(struct file * filp, char __user * buf, size_t size, l
     }
     
 
-    spin_lock_irqsave(&(stream->lock), flags); 
+    palacios_spinlock_lock_irqsave(&(stream->lock), flags); 
     total_bytes_left = ringbuf_data_len(stream->out_ring);
-    spin_unlock_irqrestore(&(stream->lock), flags);
+    palacios_spinlock_unlock_irqrestore(&(stream->lock), flags);
 
     if (total_bytes_left > 0) {
        wake_up_interruptible(&(stream->intr_queue));
@@ -141,9 +141,9 @@ stream_poll(struct file * filp, struct poll_table_struct * poll_tb) {
 
     poll_wait(filp, &(stream->intr_queue), poll_tb);
 
-    spin_lock_irqsave(&(stream->lock), flags);
+    palacios_spinlock_lock_irqsave(&(stream->lock), flags);
     data_avail = ringbuf_data_len(stream->out_ring);
-    spin_unlock_irqrestore(&(stream->lock), flags);
+    palacios_spinlock_unlock_irqrestore(&(stream->lock), flags);
 
     if (data_avail > 0) {
        return mask;
@@ -158,16 +158,22 @@ static ssize_t stream_write(struct file * filp, const char __user * buf, size_t
     char * kern_buf = NULL;
     ssize_t bytes_written = 0;
     
-    kern_buf = kmalloc(size, GFP_KERNEL);
+    kern_buf = palacios_alloc(size);
+    
+    if (!kern_buf) { 
+       ERROR("Cannot allocate buffer in stream interface\n");
+       return -EFAULT;
+    }
 
     if (copy_from_user(kern_buf, buf, size)) {
-       printk("Stream Write Failed\n");
+       ERROR("Stream Write Failed\n");
+       palacios_free(kern_buf);
        return -EFAULT;
     };
     
     bytes_written = stream->v3_stream->input(stream->v3_stream, kern_buf, size);
 
-    kfree(kern_buf);
+    palacios_free(kern_buf);
 
     return bytes_written;
 }
@@ -177,9 +183,9 @@ static int stream_release(struct inode * i, struct file * filp) {
     struct stream_state * stream = filp->private_data;
     unsigned long flags;
     
-    spin_lock_irqsave(&(stream->lock), flags);
+    palacios_spinlock_lock_irqsave(&(stream->lock), flags);
     stream->connected = 0;
-    spin_unlock_irqrestore(&(stream->lock), flags);
+    palacios_spinlock_unlock_irqrestore(&(stream->lock), flags);
 
     
     return 0;
@@ -204,17 +210,21 @@ static void * palacios_stream_open(struct v3_stream * v3_stream, const char * na
        vm_state = get_vm_ext_data(guest, "STREAM_INTERFACE");
 
        if (vm_state == NULL) {
-           printk("ERROR: Could not locate vm stream state for extension STREAM_INTERFACE\n");
+           ERROR("ERROR: Could not locate vm stream state for extension STREAM_INTERFACE\n");
            return NULL;
        }
     }
 
     if (find_stream_by_name(guest, name) != NULL) {
-       printk("Stream already exists\n");
+       ERROR("Stream already exists\n");
        return NULL;
     }
 
-    stream = kmalloc(sizeof(struct stream_state), GFP_KERNEL);
+    stream = palacios_alloc(sizeof(struct stream_state));
+    if (!stream) { 
+       ERROR("Unable to allocate stream\n");
+       return NULL;
+    }
     memset(stream, 0, sizeof(struct stream_state));
 
     stream->out_ring = create_ringbuf(STREAM_RING_LEN);
@@ -225,7 +235,7 @@ static void * palacios_stream_open(struct v3_stream * v3_stream, const char * na
     strncpy(stream->name, name, STREAM_NAME_LEN - 1);
 
     init_waitqueue_head(&(stream->intr_queue));
-    spin_lock_init(&(stream->lock));
+    palacios_spinlock_init(&(stream->lock));
 
     if (guest == NULL) {
        list_add(&(stream->stream_node), &(global_streams));
@@ -248,9 +258,9 @@ static uint64_t palacios_stream_output(struct v3_stream * v3_stream, char * buf,
     }
 
     while (bytes_written < len) {
-       spin_lock_irqsave(&(stream->lock), flags);
+       palacios_spinlock_lock_irqsave(&(stream->lock), flags);
        bytes_written += ringbuf_write(stream->out_ring, buf + bytes_written, len - bytes_written);
-       spin_unlock_irqrestore(&(stream->lock), flags);
+       palacios_spinlock_unlock_irqrestore(&(stream->lock), flags);
 
        wake_up_interruptible(&(stream->intr_queue));
 
@@ -270,7 +280,8 @@ static void palacios_stream_close(struct v3_stream * v3_stream) {
 
     free_ringbuf(stream->out_ring);
     list_del(&(stream->stream_node));
-    kfree(stream);
+    palacios_spinlock_deinit(&(stream->lock));
+    palacios_free(stream);
 
 }
 
@@ -290,9 +301,13 @@ static int stream_init( void ) {
 
 
 static int stream_deinit( void ) {
-    if (!list_empty(&(global_streams))) {
-       printk("Error removing module with open streams\n");
-       printk("TODO: free old streams... \n");
+    struct stream_state * stream = NULL;
+    struct stream_state * tmp = NULL;
+
+    list_for_each_entry_safe(stream, tmp, &(global_streams), stream_node) {
+        free_ringbuf(stream->out_ring);
+        list_del(&(stream->stream_node));
+        palacios_free(stream);
     }
 
     return 0;
@@ -312,27 +327,27 @@ static int stream_connect(struct v3_guest * guest, unsigned int cmd, unsigned lo
     
     
     if (copy_from_user(name, argp, STREAM_NAME_LEN)) {
-       printk("%s(%d): copy from user error...\n", __FILE__, __LINE__);
+       ERROR("%s(%d): copy from user error...\n", __FILE__, __LINE__);
        return -EFAULT;
     }
 
     stream = find_stream_by_name(guest, name);
 
     if (stream == NULL) {
-       printk("Could not find stream (%s)\n", name);
+       ERROR("Could not find stream (%s)\n", name);
        return -EFAULT;
     }
 
-    spin_lock_irqsave(&(stream->lock), flags);
+    palacios_spinlock_lock_irqsave(&(stream->lock), flags);
     if (stream->connected == 0) {
        stream->connected = 1;
        ret = 1;
     }
-    spin_unlock_irqrestore(&(stream->lock), flags);
+    palacios_spinlock_unlock_irqrestore(&(stream->lock), flags);
 
 
     if (ret == -1) {
-       printk("Stream (%s) already connected\n", name);
+       ERROR("Stream (%s) already connected\n", name);
        return -EFAULT;
     }
 
@@ -340,18 +355,23 @@ static int stream_connect(struct v3_guest * guest, unsigned int cmd, unsigned lo
     stream_fd = anon_inode_getfd("v3-stream", &stream_fops, stream, O_RDWR);
 
     if (stream_fd < 0) {
-       printk("Error creating stream inode for (%s)\n", name);
+       ERROR("Error creating stream inode for (%s)\n", name);
        return stream_fd;
     }
 
-    printk("Stream (%s) connected\n", name);
+    INFO("Stream (%s) connected\n", name);
 
     return stream_fd;
 }
 
 
 static int guest_stream_init(struct v3_guest * guest, void ** vm_data) {
-    struct vm_global_streams * state = kmalloc(sizeof(struct vm_global_streams), GFP_KERNEL);
+    struct vm_global_streams * state = palacios_alloc(sizeof(struct vm_global_streams));
+
+    if (!state) { 
+       ERROR("Unable to allocate state in stream init\n");
+       return -1;
+    }
 
     INIT_LIST_HEAD(&(state->open_streams));
     *vm_data = state;
@@ -364,10 +384,18 @@ static int guest_stream_init(struct v3_guest * guest, void ** vm_data) {
 
 static int guest_stream_deinit(struct v3_guest * guest, void * vm_data) {
     struct vm_global_streams * state = vm_data;
-    if (!list_empty(&(state->open_streams))) {
-       printk("Error shutting down VM with open streams\n");
-    }
 
+    struct stream_state * stream = NULL;
+    struct stream_state * tmp = NULL;
+
+    list_for_each_entry_safe(stream, tmp, &(global_streams), stream_node) {
+        free_ringbuf(stream->out_ring);
+        list_del(&(stream->stream_node));
+        palacios_free(stream);
+    }
+    
+    palacios_free(state);
+    
     return 0;
 }