#include #include struct asbuf { unsigned long ino; char *buf; size_t alloc; }; ssize_t asbuf_free_alloc(struct asbuf *buf, size_t size) { char *mem; mem = kmalloc(size, GFP_KERNEL); if (!mem) return -ENOMEM; if (buf->alloc) kfree(buf->buf); buf->buf = mem; buf->alloc = size; return 0; } void asbuf_free(struct asbuf *buf) { kfree(buf->buf); } ssize_t asbuf_to_user(struct asbuf *buf, char __user *user_buf, size_t len, loff_t *offset) { size_t chars_left, request; ssize_t uncopied, copied; if (!buf->alloc) return -EINVAL; if (*offset > buf->alloc) return -EINVAL; chars_left = buf->alloc - *offset; request = min(len, chars_left); printk(KERN_INFO "buf: %p\t alloc: %zu\t request: %zu\n", buf, buf->alloc, request); uncopied = copy_to_user(user_buf, buf->buf + *offset, request); copied = request - uncopied; *offset += copied; return copied; } ssize_t asbuf_from_user(struct asbuf *buf, const char __user *user_buf, size_t len, loff_t *offset) { ssize_t rc = 0; size_t uncopied, copied; rc = asbuf_free_alloc(buf, len); if (rc != 0) return rc; uncopied = copy_from_user(buf->buf, user_buf, len); copied = len - uncopied; *offset = 0; return copied; }