On Mon, 6 Mar 2006, Linus Torvalds wrote:
> In particular, as far as I can tell, that
>
> + /* More than offslab_limit objects will cause problems */
> + if (flags & CFLGS_OFF_SLAB && cachep->num > offslab_limit)
> + break;
>
> has been incorrectly translated for several reasons:
>
> - we shouldn't check "cachep->num > offslab_limit". We should check just
> "num > offslab_limit" (cachep->num is the _previous_ number we tested).
>
> - when we do "break", we've already incremented "gfporder", and we should
> correct for that.
>
> Now, maybe I'm just off my rocker again (I've certainly been batting 0.000
> so far, even if I think I've been finding real bugs). So who knows. But I
> get the feeling that that patch is broken.
>
> Either revert it, or try this (TOTALLY UNTESTED!!!) patch..
>
> And hey, maybe I'm just crazy.
No you're not, it's broken. However, I think you're forgetting to reset
cachep->num when we go over MAX_GFP_ORDER, no? This patch boots although
I don't hit offslab limit.
Pekka
[PATCH] slab: fix offslab_limit in calculate_slab_order
From: Linus Torvalds <[email protected]>
The commit "[PATCH] slab: extract slab order calculation to separate
function" broke offslab_limit handling:
- We should check for num instead of cachep->num because the latter
is the number of objects for the _previous_ gfp order.
- After hitting the offslab_limit, we need to correct gfporder and
calculate left_over and cachep->num for that before exiting. We
do this by keeping current state in local variables and previous
state in cachep.
Linus spotted the problem and wrote the patch. I fixed gfporder
resetting when we go over MAX_GFP_ORDER and tested it with UM.
Cc: Andrew Morton <[email protected]>
Signed-off-by: Pekka Enberg <[email protected]>
---
diff --git a/mm/slab.c b/mm/slab.c
index add05d8..fe63479 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -1628,25 +1628,22 @@ static inline size_t calculate_slab_orde
size_t size, size_t align, unsigned long flags)
{
size_t left_over = 0;
+ int gfporder;
- for (;; cachep->gfporder++) {
+ for (gfporder = 0 ; gfporder <= MAX_GFP_ORDER; gfporder++) {
unsigned int num;
size_t remainder;
- if (cachep->gfporder > MAX_GFP_ORDER) {
- cachep->num = 0;
- break;
- }
-
- cache_estimate(cachep->gfporder, size, align, flags,
- &remainder, &num);
+ cache_estimate(gfporder, size, align, flags, &remainder, &num);
if (!num)
continue;
+
/* More than offslab_limit objects will cause problems */
- if (flags & CFLGS_OFF_SLAB && cachep->num > offslab_limit)
+ if ((flags & CFLGS_OFF_SLAB) && num > offslab_limit)
break;
cachep->num = num;
+ cachep->gfporder = gfporder;
left_over = remainder;
/*
@@ -1660,6 +1657,9 @@ static inline size_t calculate_slab_orde
/* Acceptable internal fragmentation */
break;
}
+ if (cachep->gfporder > MAX_GFP_ORDER)
+ cachep->num = 0;
+
return left_over;
}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[Index of Archives]
[Kernel Newbies]
[Netfilter]
[Bugtraq]
[Photo]
[Stuff]
[Gimp]
[Yosemite News]
[MIPS Linux]
[ARM Linux]
[Linux Security]
[Linux RAID]
[Video 4 Linux]
[Linux for the blind]
[Linux Resources]