[RFC PATCH 5/6] relay: add relay_kernel_read()

2007-06-29 Thread Tom Zanussi
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()

2007-06-29 Thread Tom Zanussi
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
+ *