| From 64b011a5812107954edc50dc82fac42d440d7a76 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Fri, 30 Aug 2019 18:47:15 -0700 |
| Subject: Partially revert "kfifo: fix kfifo_alloc() and kfifo_init()" |
| |
| From: Linus Torvalds <torvalds@linux-foundation.org> |
| |
| [ Upstream commit ab9bb6318b0967671e0c9b6537c1537d51ca4f45 ] |
| |
| Commit dfe2a77fd243 ("kfifo: fix kfifo_alloc() and kfifo_init()") made |
| the kfifo code round the number of elements up. That was good for |
| __kfifo_alloc(), but it's actually wrong for __kfifo_init(). |
| |
| The difference? __kfifo_alloc() will allocate the rounded-up number of |
| elements, but __kfifo_init() uses an allocation done by the caller. We |
| can't just say "use more elements than the caller allocated", and have |
| to round down. |
| |
| The good news? All the normal cases will be using power-of-two arrays |
| anyway, and most users of kfifo's don't use kfifo_init() at all, but one |
| of the helper macros to declare a KFIFO that enforce the proper |
| power-of-two behavior. But it looks like at least ibmvscsis might be |
| affected. |
| |
| The bad news? Will Deacon refers to an old thread and points points out |
| that the memory ordering in kfifo's is questionable. See |
| |
| https://lore.kernel.org/lkml/20181211034032.32338-1-yuleixzhang@tencent.com/ |
| |
| for more. |
| |
| Fixes: dfe2a77fd243 ("kfifo: fix kfifo_alloc() and kfifo_init()") |
| Reported-by: laokz <laokz@foxmail.com> |
| Cc: Stefani Seibold <stefani@seibold.net> |
| Cc: Andrew Morton <akpm@linux-foundation.org> |
| Cc: Dan Carpenter <dan.carpenter@oracle.com> |
| Cc: Greg KH <greg@kroah.com> |
| Cc: Kees Cook <keescook@chromium.org> |
| Cc: Will Deacon <will@kernel.org> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| lib/kfifo.c | 3 ++- |
| 1 file changed, 2 insertions(+), 1 deletion(-) |
| |
| diff --git a/lib/kfifo.c b/lib/kfifo.c |
| index 90ba1eb1df06e..a94227c555510 100644 |
| --- a/lib/kfifo.c |
| +++ b/lib/kfifo.c |
| @@ -82,7 +82,8 @@ int __kfifo_init(struct __kfifo *fifo, void *buffer, |
| { |
| size /= esize; |
| |
| - size = roundup_pow_of_two(size); |
| + if (!is_power_of_2(size)) |
| + size = rounddown_pow_of_two(size); |
| |
| fifo->in = 0; |
| fifo->out = 0; |
| -- |
| 2.20.1 |
| |