lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <1265302360.28857.18.camel@wall-e>
Date:	Thu, 04 Feb 2010 17:52:40 +0100
From:	Stefani Seibold <stefani@...bold.net>
To:	Andrew Morton <akpm@...ux-foundation.org>
Cc:	linux-kernel <linux-kernel@...r.kernel.org>,
	Andi Kleen <andi@...stfloor.org>,
	Greg Kroah-Hartman <gregkh@...e.de>,
	Alan Cox <alan@...rguk.ukuu.org.uk>,
	Theodore Tso <tytso@....edu>,
	"Ira W. Snyder" <iws@...o.caltech.edu>
Subject: Re: [PATCH] enhanced reimplemention of the kfifo API

Am Mittwoch, den 03.02.2010, 15:05 -0800 schrieb Andrew Morton:
> On Wed, 03 Feb 2010 23:09:51 +0100
> Stefani Seibold <stefani@...bold.net> wrote:
> 
> > Am Mittwoch, den 03.02.2010, 12:05 -0800 schrieb Andrew Morton:
> > > On Wed, 27 Jan 2010 14:00:43 +0100
> > > Stefani Seibold <stefani@...bold.net> wrote:
> > > 
> > > > This is a complete reimplementation of the new kfifo API, which is now 
> > > > really generic, type save and type definable. 
> > > > 
> > > > 
> > > > ...
> > > >
> > > > diff -u -N -r -p linux-2.6.33-rc5.dummy/include/linux/kfifo.h linux-2.6.33-rc5.new/include/linux/kfifo.h
> > > > --- linux-2.6.33-rc5.dummy/include/linux/kfifo.h	1970-01-01 01:00:00.000000000 +0100
> > > > +++ linux-2.6.33-rc5.new/include/linux/kfifo.h	2010-01-27 13:34:06.324991898 +0100
> > > >
> > > > ...
> > > >
> > > > +/*
> > > > + * DECLARE_KFIFO_PTR - macro to declare a fifo pointer object
> > > > + * @fifo: name of the declared fifo
> > > > + * @type: type of the fifo elements
> > > > + * @size: the number of elements in the fifo, this must be a power of 2.
> > > > + */
> > > 
> > > Throughout this patch the comments are in kerneldoc form, but they
> > > don't use the /** opening token, so the kerneldoc tools will ignore them.
> > > 
> > > Please fix that up and test it.
> > > 
> > > > +#define DECLARE_KFIFO_PTR(fifo, type)	STRUCT_KFIFO_PTR(type) fifo
> > > > +
> > > > +/* helper macro */
> > > > +#define	__is_kfifo_ptr(fifo)	(sizeof(*fifo) == sizeof(struct __kfifo))
> > > 
> > > This is weird.  It's a compile-time constant.  What's it here for?
> > 
> > I need it to distinguish between real in place fifo, where the fifo
> > array is a part of the structure, and the fifo type where the array is
> > outside of the fifo structure.
> 
> OK, please add a comment?

I will do this.

> 
> > > > +/*
> > > > + * INIT_KFIFO - Initialize a fifo declared by DECLARE_KFIFO
> > > > + * @fifo: name of the declared fifo datatype
> > > > + */
> > > > +#define INIT_KFIFO(fifo)	fifo = __kfifo_initializer(fifo)
> > > 
> > > Some versions of gcc generate quite poor code for
> > > 
> > > 	struct foo f = { ... };
> > > 
> > > It would generate an instance of the struct into the stack and then
> > > would memcpy it over, iirc.  Please take a look, see if that's
> > > happening with this construct (might need to use an old gcc version)
> > > and if so, see if there's a fix?
> > > 
> > 
> > The current version of the kfifo implementation did it in the same way.
> > Why is it now wrong?
> 
> It was wrong before, too.
> 
> > Which gcc version do you mean?
> 
> I don't recall.  The oldest gcc the kernel permits is 3.2, so checking
> any 3.x should be OK.
> 

I will try to build a gcc 3 and check it.

> > > > +/*
> > > > + * kfifo_initialized - Check if kfifo is initialized.
> > > > + * @fifo: fifo to check
> > > > + * Return %true if FIFO is initialized, otherwise %false.
> > > > + * Assumes the fifo was 0 before.
> > > > + *
> > > > + * Note: for in place fifo's this macro returns alway true
> > > > + */
> > > > +#define kfifo_initialized(fifo) ((fifo)->kfifo.data != NULL)
> > > 
> > > kfifo_initialized() is suspicious.  Any code which doesn't know whether
> > > its kfifo was initialised is probably confused, lame and broken. 
> > > Fortunately kfifo_initialized() is not used anywhere.  Please prepare a
> > > separate patch to kill it sometime.
> > > 
> > 
> > This function was introduced as a patch by andi kleen and you have it
> > already applied.
> 
> Let's delete it?
> 

Can you clarify this with andi please?

> > > > +/*
> > > > + * kfifo_esize - returns the size of the element managed by the fifo
> > > > + * @fifo: the fifo to be used.
> > > > + */
> > > > +#define kfifo_esize(fifo)	((fifo)->kfifo.esize)
> > > 
> > > This doesn't seem to be used anywhere either.
> > > 
> > 
> > It is a part of the API. It returns the the size of the handled element,
> > If a driver developer need it, it is there.
> 
> Well, if there's no proven need for it now, it will remain dead code
> for an unknown period of time.
> 
> Also, there was no need to implement this as a macro (was there?).  If
> not, conversion to a more typesafe C function would be better.
> 

It is not possible to write this as a function, because the parameter
fifo is an arbitrary type. There is no fifo type, only a template and a
macro which generates a fifo which managed a given type, where the
generic "struct __kfifo" part is embedded.

> > > > +/*
> > > > + * kfifo_recsize - returns the size of the record length field
> > > > + * @fifo: the fifo to be used.
> > > > + */
> > > > +#define kfifo_recsize(fifo)	(sizeof(*(fifo)->rectype))
> > > 
> > > Neither is this.  What's going on?
> > > 
> > 
> > Dito... This returns the size of the record length field. 0 means this
> > is not a variable record fifo.
> 
> ditto.
> 
> > > > +/*
> > > > + * kfifo_out_locked - gets some data from the fifo using a spinlock for locking
> > > > + * @fifo: the fifo to be used.
> > > > + * @buf: pointer to the storage buffer
> > > > + * @n: max. number of elements to get
> > > > + * @lock: pointer to the spinlock to use for locking.
> > > > + *
> > > > + * This macro get the data from the fifo and return the numbers of elements
> > > > + * copied.
> > > > + */
> > > > +#define	kfifo_out_locked(fifo, buf, n, lock) \
> > > > +__kfifo_check( \
> > > > +({ \
> > > > +	unsigned long __flags; \
> > > > +	unsigned int __ret; \
> > > > +	spin_lock_irqsave(lock, __flags); \
> > > > +	__ret = kfifo_out(fifo, buf, n); \
> > > > +	spin_unlock_irqrestore(lock, __flags); \
> > > > +	__ret; \
> > > > +}) \
> > > > +)
> > > 
> > > This is poorly named.  Generally "foo_locked" is to be called when the
> > > caller has already taken the lock.  This identifier inverts that
> > > convention.
> > > 
> > 
> > This is the same name as the current kfifo API. Renaming it would break
> > a lot of drivers. But if there is no complain and you insist i will
> > rename it and fix the current users.
> 
> argh, we goofed.
> 
> yeah, it'd be nice to fix it sometime, please.  Not urgent.
> 
> A good way to fix it would be to add a new function with a new name
> then migrate all callers over to that name then when it's done, remove
> the old name.
> 

I will do this in the next release. Would be kfifo_out_spinlocked() and
kfifo_in_spinlocked() for the new names okay?

> > > > + * @fifo: the fifo to be used.
> > > > + * @to: where the data must be copied.
> > > > + * @len: the size of the destination buffer.
> > > > + * @copied: pointer to output variable to store the number of copied bytes.
> > > > + *
> > > > + * This macro copies at most @len bytes from the fifo into the
> > > > + * @to buffer and returns -EFAULT/0.
> > > > + *
> > > > + * Note that with only one concurrent reader and one concurrent
> > > > + * writer, you don't need extra locking to use these macro.
> > > > + */
> > > > +#define	kfifo_to_user(fifo, to, len, copied) \
> > > > +__kfifo_check( \
> > > > +({ \
> > > > +	typeof(fifo + 1) __tmp = (fifo); \
> > > > +	void __user *__to = (to); \
> > > > +	unsigned int __len = (len); \
> > > > +	unsigned int *__copied = (copied); \
> > > > +	const size_t __recsize = sizeof(*__tmp->rectype); \
> > > > +	struct __kfifo *__kfifo = &__tmp->kfifo; \
> > > > +	(__recsize) ? \
> > > > +	__kfifo_to_user_r(__kfifo, __to, __len, __copied, __recsize) : \
> > > > +	__kfifo_to_user(__kfifo, __to, __len, __copied); \
> > > > +}) \
> > > > +)
> > > 
> > > Do these have any callers?
> > > 
> > 
> > Currently not, but this is a part of the current kfifo implementation. A
> > lot of developer like this idea and it will be used in the near future.
> 
> OK.  Please describe the presently-unused interfaces in the changelog,
> with particular attention to the reason for including them at this
> time.
> 

OK

> > > > +static inline unsigned int kfifo_unused(struct __kfifo *fifo)
> > > > +{
> > > > +	return (fifo->mask + 1) - (fifo->in - fifo->out);
> > > > +}
> > > 
> > > hm, how does this differ from kfifo_avail()?
> > > 
> > 
> > This is similar to kfifo_avail, but due the nature of macro and type
> > conversation i have not longer the original type information available.
> > So i can't call the macros in kfifo.h from the functions defined in
> > kfifo.c.
> 
> OK, please add a comment there.  (As a general rule: if this reader
> needed more info then other readers will want more info as well).
> 
> > > > +static unsigned long kfifo_copy_from_user(struct __kfifo *fifo,
> > > > +	const void *src, unsigned int len, unsigned int off,
> > > > +	unsigned int *copied)
> > > > +{
> > > > +	unsigned int size = fifo->mask + 1;
> > > > +	unsigned int esize = fifo->esize;
> > > > +	unsigned int l;
> > > > +	unsigned long ret;
> > > > +
> > > > +	off &= fifo->mask;
> > > > +	if (esize != 1) {
> > > > +		off *= esize;
> > > > +		size *= esize;
> > > > +		len *= esize;
> > > > +	}
> > > > +	l = min(len, size - off);
> > > > +
> > > > +	ret = copy_from_user(fifo->data + off, src, l);
> > > > +	if (unlikely(ret))
> > > > +		ret = roundup_diff(ret + len - l, esize);
> > > > +	else {
> > > > +		ret = copy_from_user(fifo->data, src + l, len - l);
> > > > +		if (unlikely(ret))
> > > > +			ret = roundup_diff(ret, esize);
> > > > +	}
> > > > +	smp_wmb();
> > > > +	if (copied)
> > > 
> > > Can `copied' ever be NULL?  If not, remove this test.
> > 
> > It was only a feature. If you don't like i will remove it.
> 
> No strong opinion.  But if present callers don't pass NULL then that's
> a sign that future callers won't, too.  We may as well save the
> speed/space overhead until we actually need it.
> 
> 

This will be fixed in the next release.

One offer to solve the egg and chicken problem: Let us include the
functions kfifo_to_user(), kfifo_from_user(),  kfifo_esize(),
kfifo_recsize() and the dynamic record handling. If there will be no
users in at least 9 months we remove it from the API. We talk here about
400 bytes of code.

In the mean time me and other developer will have a change to modify the
existing driver to the new API and/or post drivers or core kernel code
which is using this functionality. 

Stefani


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ