[RFC PATCH 5/6] relay: add relay_kernel_read()
This patch adds a relay_kernel_read() function to relay, which allows kernel clients to easily extract only the data (i.e. and skip over padding) from a channel buffer. Signed-off-by: Tom Zanussi <[EMAIL PROTECTED]> Signed-off-by: David Wilder <[EMAIL PROTECTED]> --- Documentation/filesystems/relay.txt | 14 ++ include/linux/relay.h |5 ++ kernel/relay.c | 79 3 files changed, 90 insertions(+), 8 deletions(-) diff --git a/Documentation/filesystems/relay.txt b/Documentation/filesystems/relay.txt index d31113a..e9f10cf 100644 --- a/Documentation/filesystems/relay.txt +++ b/Documentation/filesystems/relay.txt @@ -185,6 +185,7 @@ TBD(curr. line MT:/API/) relay_buf_full(buf) subbuf_start_reserve(buf, length) +relay_kernel_read(rbuf, buffer, count, ppos) Creating a channel @@ -446,6 +447,19 @@ closed. Misc +relay_kernel_read() provides the same functionality as the userspace +read(2) implementation, but instead of copying the relay buffer data +to a buffer in user space, the data is copied to the supplied kernel +buffer target. As with user space read(), the sub-buffer padding is +automatically removed from the output and is not seen by the reader. +In the case of relay_kernel_read(), there is no file object associated +with the reader, so it needs to supply a pointer to a ppos variable, +which will be used to maintain the current read position instead. +This is useful for applications that may want to provide an +alternative interface to the relay buffer data or who want access to +the buffer data without needing to know anything about buffer +internals. + Some applications may want to keep a channel around and re-use it rather than open and close a new channel for each use. relay_reset() can be used for this purpose - it resets a channel to its initial diff --git a/include/linux/relay.h b/include/linux/relay.h index aca45fa..6caedef 100644 --- a/include/linux/relay.h +++ b/include/linux/relay.h @@ -181,6 +181,11 @@ extern int relay_buf_full(struct rchan_buf *buf); extern size_t relay_switch_subbuf(struct rchan_buf *buf, size_t length); +extern ssize_t relay_kernel_read(struct rchan_buf *rbuf, +char *buffer, +size_t count, +loff_t *ppos); + /** * relay_write - write data into the channel * @chan: relay channel diff --git a/kernel/relay.c b/kernel/relay.c index 6806636..ed58ee6 100644 --- a/kernel/relay.c +++ b/kernel/relay.c @@ -987,6 +987,24 @@ static size_t relay_file_read_end_pos(struct rchan_buf *buf, return end_pos; } +/** + * subbuf_kernel_read_actor - read up to one subbuf's worth of data + */ +static int subbuf_kernel_read_actor(size_t read_start, + struct rchan_buf *buf, + size_t avail, + read_descriptor_t *desc, + read_actor_t actor) +{ + void *from = buf->start + read_start; + memcpy(desc->arg.data, from, avail); + desc->arg.data += avail; + desc->written += avail; + desc->count -= avail; + + return avail; +} + /* * subbuf_read_actor - read up to one subbuf's worth of data */ @@ -1058,19 +1076,17 @@ typedef int (*subbuf_actor_t) (size_t read_start, /* * relay_file_read_subbufs - read count bytes, bridging subbuf boundaries */ -static ssize_t relay_file_read_subbufs(struct file *filp, loff_t *ppos, +static ssize_t relay_file_read_subbufs(struct rchan_buf *buf, loff_t *ppos, subbuf_actor_t subbuf_actor, read_actor_t actor, read_descriptor_t *desc) { - struct rchan_buf *buf = filp->private_data; size_t read_start, avail; int ret; if (!desc->count) return 0; - mutex_lock(>f_path.dentry->d_inode->i_mutex); do { if (!relay_file_read_avail(buf, *ppos)) break; @@ -1090,23 +1106,62 @@ static ssize_t relay_file_read_subbufs(struct file *filp, loff_t *ppos, *ppos = relay_file_read_end_pos(buf, read_start, ret); } } while (desc->count && ret); - mutex_unlock(>f_path.dentry->d_inode->i_mutex); return desc->written; } +/** + * relay_kernel_read - read relay buffer into kernel target buffer + * @rbuf: the relay buffer struct + * @buffer: the target kernel buffer + * @count: number of bytes to read + * @ppos: pointer to read position variable + * + * Returns the number of bytes copied into buffer. + * + * Performs the same function as user space read, except that + * relay buffer contents are copied to the supplied kernel buffer +
[RFC PATCH 5/6] relay: add relay_kernel_read()
This patch adds a relay_kernel_read() function to relay, which allows kernel clients to easily extract only the data (i.e. and skip over padding) from a channel buffer. Signed-off-by: Tom Zanussi [EMAIL PROTECTED] Signed-off-by: David Wilder [EMAIL PROTECTED] --- Documentation/filesystems/relay.txt | 14 ++ include/linux/relay.h |5 ++ kernel/relay.c | 79 3 files changed, 90 insertions(+), 8 deletions(-) diff --git a/Documentation/filesystems/relay.txt b/Documentation/filesystems/relay.txt index d31113a..e9f10cf 100644 --- a/Documentation/filesystems/relay.txt +++ b/Documentation/filesystems/relay.txt @@ -185,6 +185,7 @@ TBD(curr. line MT:/API/) relay_buf_full(buf) subbuf_start_reserve(buf, length) +relay_kernel_read(rbuf, buffer, count, ppos) Creating a channel @@ -446,6 +447,19 @@ closed. Misc +relay_kernel_read() provides the same functionality as the userspace +read(2) implementation, but instead of copying the relay buffer data +to a buffer in user space, the data is copied to the supplied kernel +buffer target. As with user space read(), the sub-buffer padding is +automatically removed from the output and is not seen by the reader. +In the case of relay_kernel_read(), there is no file object associated +with the reader, so it needs to supply a pointer to a ppos variable, +which will be used to maintain the current read position instead. +This is useful for applications that may want to provide an +alternative interface to the relay buffer data or who want access to +the buffer data without needing to know anything about buffer +internals. + Some applications may want to keep a channel around and re-use it rather than open and close a new channel for each use. relay_reset() can be used for this purpose - it resets a channel to its initial diff --git a/include/linux/relay.h b/include/linux/relay.h index aca45fa..6caedef 100644 --- a/include/linux/relay.h +++ b/include/linux/relay.h @@ -181,6 +181,11 @@ extern int relay_buf_full(struct rchan_buf *buf); extern size_t relay_switch_subbuf(struct rchan_buf *buf, size_t length); +extern ssize_t relay_kernel_read(struct rchan_buf *rbuf, +char *buffer, +size_t count, +loff_t *ppos); + /** * relay_write - write data into the channel * @chan: relay channel diff --git a/kernel/relay.c b/kernel/relay.c index 6806636..ed58ee6 100644 --- a/kernel/relay.c +++ b/kernel/relay.c @@ -987,6 +987,24 @@ static size_t relay_file_read_end_pos(struct rchan_buf *buf, return end_pos; } +/** + * subbuf_kernel_read_actor - read up to one subbuf's worth of data + */ +static int subbuf_kernel_read_actor(size_t read_start, + struct rchan_buf *buf, + size_t avail, + read_descriptor_t *desc, + read_actor_t actor) +{ + void *from = buf-start + read_start; + memcpy(desc-arg.data, from, avail); + desc-arg.data += avail; + desc-written += avail; + desc-count -= avail; + + return avail; +} + /* * subbuf_read_actor - read up to one subbuf's worth of data */ @@ -1058,19 +1076,17 @@ typedef int (*subbuf_actor_t) (size_t read_start, /* * relay_file_read_subbufs - read count bytes, bridging subbuf boundaries */ -static ssize_t relay_file_read_subbufs(struct file *filp, loff_t *ppos, +static ssize_t relay_file_read_subbufs(struct rchan_buf *buf, loff_t *ppos, subbuf_actor_t subbuf_actor, read_actor_t actor, read_descriptor_t *desc) { - struct rchan_buf *buf = filp-private_data; size_t read_start, avail; int ret; if (!desc-count) return 0; - mutex_lock(filp-f_path.dentry-d_inode-i_mutex); do { if (!relay_file_read_avail(buf, *ppos)) break; @@ -1090,23 +1106,62 @@ static ssize_t relay_file_read_subbufs(struct file *filp, loff_t *ppos, *ppos = relay_file_read_end_pos(buf, read_start, ret); } } while (desc-count ret); - mutex_unlock(filp-f_path.dentry-d_inode-i_mutex); return desc-written; } +/** + * relay_kernel_read - read relay buffer into kernel target buffer + * @rbuf: the relay buffer struct + * @buffer: the target kernel buffer + * @count: number of bytes to read + * @ppos: pointer to read position variable + * + * Returns the number of bytes copied into buffer. + * + * Performs the same function as user space read, except that + * relay buffer contents are copied to the supplied kernel buffer + *