I am writing a kernel module, that when written to will allocate kernel memory, but as of now does nothing when read from, here is what I got so far, but it locks up my system when I run this command "echo "hello there" > /dev/testdev"
Code:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/devfs_fs_kernel.h>
#define DATA_SIZE 256
/* Add semaphore support. */

int device_open(struct inode *inode, struct file *filp);
int device_release(struct inode *inode, struct file *filp);
ssize_t device_read(struct file *filp, char *buf, size_t count, loff_t *pos);
ssize_t device_write(struct file *filp, const char *buf, size_t count, loff_t *pos);
static int major;

static struct file_operations fops = {
        .open = device_open,
        .release = device_release,
        .read = device_read,
        .write = device_write
};
static struct device_data {
        char data[DATA_SIZE];
        struct device_data *next;
};
static struct device_data *first;
static struct device_data *wkdata;
int device_open(struct inode *inode, struct file *filp) {
        MOD_INC_USE_COUNT;
        return 0;
}
int device_release(struct inode *inode, struct file *filp) {
        MOD_DEC_USE_COUNT;
        return 0;
}
ssize_t device_read(struct file *filp, char *buf, size_t count, loff_t *pos) {
        return 0;
}
ssize_t device_write(struct file *filp, const char *buf, size_t count, loff_t *pos) {
        wkdata = first;
        while(1) {
                if(wkdata == (struct device_data *)NULL)
                        return -1;
                while(count > DATA_SIZE) {
                        printk("\nbefore memcpy.\n");
                        memcpy(wkdata->data, buf, DATA_SIZE);
                        printk("After memcpy.\n");
                        count-=DATA_SIZE;
                        wkdata->next = (struct device_data *)kmalloc(sizeof(struct device_data), GFP_KERNEL);
                        wkdata = wkdata->next;
                }
                if(count > 0) {
                        wkdata->next = (struct device_data *)kmalloc(sizeof(struct device_data), GFP_KERNEL);
                        wkdata = wkdata->next;
                        memcpy(wkdata->data, buf, count);
                }
        }
        return 0;
}
static __init int device_init(void) {
        major = register_chrdev(0, "testdev", &fops);
        devfs_register(NULL, "testdev", DEVFS_FL_AUTO_DEVNUM, 0, 0, S_IFCHR | S_IRUGO | S_IWUGO, &fops, 0);
        first = (struct device_data *)kmalloc(sizeof(struct device_data), GFP_KERNEL);
        return 0;
}
static __exit void device_exit(void) {
}
module_init(device_init);
module_exit(device_exit);
MODULE_LICENSE("GPL");