From: Nelson Castillo <nelsoneci@gmail.com>
To: Stelian Pop <stelian@popies.net>
Cc: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
Subject: Re: [RFC][PATCH 1/1] support for user-space buffers in kfifo
Date: Tue, 12 Jun 2007 21:21:24 -0500 [thread overview]
Message-ID: <20070613022124.GA31974@emqbit.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 5295 bytes --]
On 6/12/07, Stelian Pop <stelian@popies.net> wrote:
> Le mardi 12 juin 2007 à 11:24 -0500, Nelson Castillo a écrit :
> > On 6/12/07, Stelian Pop <stelian@popies.net> wrote:
> > (cut)
> > > accessing userspace memory with a spinlock taken (moreover an
> > > irqsave()
> > > one) is bad bad bad.
> >
> > Hi Stelian.
> >
> > I'm sending the new patch without kfifo_put_user and kfifo_get_user.
>
> Ok, I have a few formatting/documentation comments:
Applied, thanks.
> Other than that I'm ok with this patch.
Submitting.
Regards, Nelson.-
Signed-off-by: Nelson Castillo <nelson@emqbit.com>
---
diff --git a/include/linux/kfifo.h b/include/linux/kfifo.h
index 404f446..5c4c416 100644
--- a/include/linux/kfifo.h
+++ b/include/linux/kfifo.h
@@ -41,8 +41,13 @@ extern struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask,
extern void kfifo_free(struct kfifo *fifo);
extern unsigned int __kfifo_put(struct kfifo *fifo,
unsigned char *buffer, unsigned int len);
+extern int __kfifo_put_user(struct kfifo *fifo,
+ const unsigned char __user *buffer,
+ unsigned int len);
extern unsigned int __kfifo_get(struct kfifo *fifo,
unsigned char *buffer, unsigned int len);
+extern int __kfifo_get_user(struct kfifo *fifo, unsigned char __user *buffer,
+ unsigned int len);
/**
* __kfifo_reset - removes the entire FIFO contents, no locking version
diff --git a/kernel/kfifo.c b/kernel/kfifo.c
index cee4191..b11024e 100644
--- a/kernel/kfifo.c
+++ b/kernel/kfifo.c
@@ -23,6 +23,7 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/err.h>
+#include <asm/uaccess.h>
#include <linux/kfifo.h>
/**
@@ -150,6 +151,61 @@ unsigned int __kfifo_put(struct kfifo *fifo,
EXPORT_SYMBOL(__kfifo_put);
/**
+ * __kfifo_put_user - puts some data into the FIFO, from userspace
+ * We don't have a locking version because copy_from_user
+ * might sleep and you must not sleep holding a spinlock.
+ *
+ * @fifo: the fifo to be used.
+ * @buffer: the user space data to be added.
+ * @len: the length of the data to be added.
+ *
+ * This function copies at most @len bytes from the @buffer into
+ * the FIFO depending on the free space, and returns the number of
+ * bytes copied or -EFAULT if copy_from_user fails.
+ *
+ * Note that with only one concurrent reader and one concurrent
+ * writer, you don't need extra locking to use these functions.
+ */
+int __kfifo_put_user(struct kfifo *fifo, const unsigned char __user *buffer,
+ unsigned int len)
+{
+ unsigned int l;
+
+ len = min(len, fifo->size - fifo->in + fifo->out);
+
+ /*
+ * Ensure that we sample the fifo->out index -before- we
+ * start putting bytes into the kfifo.
+ */
+
+ smp_mb();
+
+ /* first put the data starting from fifo->in to buffer end */
+ l = min(len, fifo->size - (fifo->in & (fifo->size - 1)));
+
+ if (copy_from_user(fifo->buffer + (fifo->in & (fifo->size - 1)),
+ buffer, l))
+ return -EFAULT;
+
+
+ /* then put the rest (if any) at the beginning of the buffer */
+ if (copy_from_user(fifo->buffer, buffer + l, len - l))
+ return -EFAULT;
+
+ /*
+ * Ensure that we add the bytes to the kfifo -before-
+ * we update the fifo->in index.
+ */
+
+ smp_wmb();
+
+ fifo->in += len;
+
+ return (int)len;
+}
+EXPORT_SYMBOL(__kfifo_put_user);
+
+/**
* __kfifo_get - gets some data from the FIFO, no locking version
* @fifo: the fifo to be used.
* @buffer: where the data must be copied.
@@ -194,3 +250,57 @@ unsigned int __kfifo_get(struct kfifo *fifo,
return len;
}
EXPORT_SYMBOL(__kfifo_get);
+
+/**
+ * __kfifo_get_user - gets some data from the FIFO to userspace
+ * We don't have a locking version because copy_to_user
+ * might sleep and you must not sleep holding a spinlock.
+ * @fifo: the fifo to be used.
+ * @buffer: user space buffer where the data must be copied.
+ * @len: the size of the destination buffer.
+ *
+ * This function copies at most @len bytes from the FIFO into the
+ * @buffer and returns the number of bytes copied or -EFAULT if
+ * copy_to_user fails.
+ *
+ * Note that with only one concurrent reader and one concurrent
+ * writer, you don't need extra locking to use these functions.
+ */
+
+int __kfifo_get_user(struct kfifo *fifo,
+ unsigned char __user *buffer, unsigned int len)
+{
+ unsigned int l;
+
+ len = min(len, fifo->in - fifo->out);
+
+ /*
+ * Ensure that we sample the fifo->in index -before- we
+ * start removing bytes from the kfifo.
+ */
+
+ smp_rmb();
+
+ /* first get the data from fifo->out until the end of the buffer */
+ l = min(len, fifo->size - (fifo->out & (fifo->size - 1)));
+
+ if (copy_to_user(buffer, fifo->buffer + (fifo->out & (fifo->size - 1)), l))
+ return -EFAULT;
+
+ /* then get the rest (if any) from the beginning of the buffer */
+ if (copy_to_user(buffer + l, fifo->buffer, len - l))
+ return -EFAULT;
+
+ /*
+ * Ensure that we remove the bytes from the kfifo -before-
+ * we update the fifo->out index.
+ */
+
+ smp_mb();
+
+ fifo->out += len;
+
+ return (int)len;
+}
+EXPORT_SYMBOL(__kfifo_get_user);
+
--
http://arhuaco.org
http://emQbit.com
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
next reply other threads:[~2007-06-13 2:21 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-06-13 2:21 Nelson Castillo [this message]
2007-06-13 6:00 ` [RFC][PATCH 1/1] support for user-space buffers in kfifo Stelian Pop
-- strict thread matches above, loose matches on Subject: below --
2007-06-12 16:24 Nelson Castillo
2007-06-12 22:12 ` Stelian Pop
2007-06-11 21:26 Nelson Castillo
2007-06-12 13:43 ` Stelian Pop
2007-06-12 14:55 ` Nelson Castillo
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=20070613022124.GA31974@emqbit.com \
--to=nelsoneci@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=stelian@popies.net \
/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.