From: Tom Zanussi <zanussi@us.ibm.com>
To: linux-kernel@vger.kernel.org
Cc: dwilder@us.ibm.com, HOLZHEU@de.ibm.com
Subject: [RFC PATCH 5/6] relay: add relay_kernel_read()
Date: Fri, 29 Jun 2007 22:24:17 -0500 [thread overview]
Message-ID: <1183173857.24291.141.camel@ubuntu> (raw)
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 <zanussi@us.ibm.com>
Signed-off-by: David Wilder <dwilder@us.ibm.com>
---
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
+ * instead of a user space buffer. The user must supply a ppos
+ * variable, initialized to 0, which will be used to maintain the
+ * current read position.
+ */
+ssize_t relay_kernel_read(struct rchan_buf *rbuf,
+ char *buffer,
+ size_t count,
+ loff_t *ppos)
+{
+ read_descriptor_t desc;
+
+ desc.written = 0;
+ desc.count = count;
+ desc.arg.buf = buffer;
+ desc.error = 0;
+
+ return relay_file_read_subbufs(rbuf, ppos, subbuf_kernel_read_actor,
+ NULL, &desc);
+}
+EXPORT_SYMBOL_GPL(relay_kernel_read);
+
static ssize_t relay_file_read(struct file *filp,
char __user *buffer,
size_t count,
loff_t *ppos)
{
+ struct rchan_buf *rbuf = filp->private_data;
+ size_t ret;
read_descriptor_t desc;
+
desc.written = 0;
desc.count = count;
desc.arg.buf = buffer;
desc.error = 0;
- return relay_file_read_subbufs(filp, ppos, subbuf_read_actor,
- NULL, &desc);
+
+ mutex_lock(&filp->f_dentry->d_inode->i_mutex);
+ ret = relay_file_read_subbufs(rbuf, ppos, subbuf_read_actor,
+ NULL, &desc);
+ mutex_unlock(&filp->f_dentry->d_inode->i_mutex);
+
+ return ret;
}
static ssize_t relay_file_sendfile(struct file *filp,
@@ -1115,13 +1170,21 @@ static ssize_t relay_file_sendfile(struct file *filp,
read_actor_t actor,
void *target)
{
+ struct rchan_buf *rbuf = filp->private_data;
+ size_t ret;
read_descriptor_t desc;
+
desc.written = 0;
desc.count = count;
desc.arg.data = target;
desc.error = 0;
- return relay_file_read_subbufs(filp, ppos, subbuf_send_actor,
- actor, &desc);
+
+ mutex_lock(&filp->f_dentry->d_inode->i_mutex);
+ ret = relay_file_read_subbufs(rbuf, ppos, subbuf_send_actor,
+ actor, &desc);
+ mutex_unlock(&filp->f_dentry->d_inode->i_mutex);
+
+ return ret;
}
const struct file_operations relay_file_operations = {
reply other threads:[~2007-06-30 3:26 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1183173857.24291.141.camel@ubuntu \
--to=zanussi@us.ibm.com \
--cc=HOLZHEU@de.ibm.com \
--cc=dwilder@us.ibm.com \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.