X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=linux_module%2Fiface-stream.c;h=d6c6331ca11c7cdf84ab3b232cc8e7c546804b07;hb=1f8ac11d4550b1113d9a8c23e62b236cb8ad8404;hp=9cb89e58650a86a0086a68e75a37ef2e6c4b3007;hpb=ef34565873989f5b0240f7f9911c3666a69587c9;p=palacios.git diff --git a/linux_module/iface-stream.c b/linux_module/iface-stream.c index 9cb89e5..d6c6331 100644 --- a/linux_module/iface-stream.c +++ b/linux_module/iface-stream.c @@ -18,12 +18,12 @@ #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; }