Adds a relay_kernel_read() used by logdev_relay in logdev-0.5.4.patch. --- include/linux/relay.h | 4 +++ kernel/relay.c | 54 ++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 46 insertions(+), 12 deletions(-) Index: linux-2.6.21.5-rt20/include/linux/relay.h =================================================================== --- linux-2.6.21.5-rt20.orig/include/linux/relay.h 2007-07-11 10:09:49.000000000 +0200 +++ linux-2.6.21.5-rt20/include/linux/relay.h 2007-07-11 14:28:47.000000000 +0200 @@ -178,6 +178,10 @@ extern int relay_buf_full(struct rchan_b extern size_t relay_switch_subbuf(struct rchan_buf *buf, size_t length); +extern ssize_t relay_kernel_read(char *buffer, + size_t count, + loff_t *ppos, + struct rchan_buf *kbuf); /** * relay_write - write data into the channel Index: linux-2.6.21.5-rt20/kernel/relay.c =================================================================== --- linux-2.6.21.5-rt20.orig/kernel/relay.c 2007-07-11 10:09:49.000000000 +0200 +++ linux-2.6.21.5-rt20/kernel/relay.c 2007-07-11 14:28:47.000000000 +0200 @@ -946,14 +946,21 @@ static int subbuf_read_actor(size_t read struct rchan_buf *buf, size_t avail, read_descriptor_t *desc, - read_actor_t actor) + read_actor_t actor, + int kernel_reader) { void *from; int ret = 0; + int err = 0; from = buf->start + read_start; ret = avail; - if (copy_to_user(desc->arg.buf, from, avail)) { + + if (kernel_reader) + memcpy(desc->arg.buf, from, avail); + else + err = copy_to_user(desc->arg.buf, from, avail); + if (err) { desc->error = -EFAULT; ret = 0; } @@ -971,7 +978,8 @@ static int subbuf_send_actor(size_t read struct rchan_buf *buf, size_t avail, read_descriptor_t *desc, - read_actor_t actor) + read_actor_t actor, + int kernel_reader) { unsigned long pidx, poff; unsigned int subbuf_pages; @@ -1005,7 +1013,8 @@ typedef int (*subbuf_actor_t) (size_t re struct rchan_buf *buf, size_t avail, read_descriptor_t *desc, - read_actor_t actor); + read_actor_t actor, + int kernel_reader); /* * relay_file_read_subbufs - read count bytes, bridging subbuf boundaries @@ -1013,16 +1022,21 @@ typedef int (*subbuf_actor_t) (size_t re static ssize_t relay_file_read_subbufs(struct file *filp, loff_t *ppos, subbuf_actor_t subbuf_actor, read_actor_t actor, - read_descriptor_t *desc) + read_descriptor_t *desc, + struct rchan_buf *kbuf) { - struct rchan_buf *buf = filp->private_data; + struct rchan_buf *buf; size_t read_start, avail; - int ret; + int ret, kernel_reader; + + buf = kbuf ? kbuf : filp->private_data; + kernel_reader = filp ? 0 : 1; if (!desc->count) return 0; - mutex_lock(&filp->f_path.dentry->d_inode->i_mutex); + if (filp) + mutex_lock(&filp->f_path.dentry->d_inode->i_mutex); do { if (!relay_file_read_avail(buf, *ppos)) break; @@ -1033,7 +1047,7 @@ static ssize_t relay_file_read_subbufs(s break; avail = min(desc->count, avail); - ret = subbuf_actor(read_start, buf, avail, desc, actor); + ret = subbuf_actor(read_start, buf, avail, desc, actor, kernel_reader); if (desc->error < 0) break; @@ -1042,7 +1056,8 @@ static ssize_t relay_file_read_subbufs(s *ppos = relay_file_read_end_pos(buf, read_start, ret); } } while (desc->count && ret); - mutex_unlock(&filp->f_path.dentry->d_inode->i_mutex); + if (filp) + mutex_unlock(&filp->f_path.dentry->d_inode->i_mutex); return desc->written; } @@ -1058,8 +1073,23 @@ static ssize_t relay_file_read(struct fi desc.arg.buf = buffer; desc.error = 0; return relay_file_read_subbufs(filp, ppos, subbuf_read_actor, - NULL, &desc); + NULL, &desc, NULL); +} + +ssize_t relay_kernel_read(char *buffer, + size_t count, + loff_t *ppos, + struct rchan_buf *kbuf) +{ + read_descriptor_t desc; + desc.written = 0; + desc.count = count; + desc.arg.buf = buffer; + desc.error = 0; + return relay_file_read_subbufs(NULL, ppos, subbuf_read_actor, + NULL, &desc, kbuf); } +EXPORT_SYMBOL_GPL(relay_kernel_read); static ssize_t relay_file_sendfile(struct file *filp, loff_t *ppos, @@ -1073,7 +1103,7 @@ static ssize_t relay_file_sendfile(struc desc.arg.data = target; desc.error = 0; return relay_file_read_subbufs(filp, ppos, subbuf_send_actor, - actor, &desc); + actor, &desc, NULL); } const struct file_operations relay_file_operations = {