diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-06 20:44:43 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-06 20:44:43 -0500 |
commit | 9888e6fa7b68d9c8cc2c162a90979825ab45150a (patch) | |
tree | 83e46fb733008fa753269d338f90ad255cc59f53 /mm/slab.c | |
parent | f716d8303345698728d9f8ce76a82a795a5be275 (diff) |
slab: clarify and fix calculate_slab_order()
If we triggered the 'offslab_limit' test, we would return with
cachep->gfporder incremented once too many times.
This clarifies the logic somewhat, and fixes that bug.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'mm/slab.c')
-rw-r--r-- | mm/slab.c | 24 |
1 files changed, 12 insertions, 12 deletions
@@ -1628,36 +1628,36 @@ static inline size_t calculate_slab_order(struct kmem_cache *cachep, | |||
1628 | size_t size, size_t align, unsigned long flags) | 1628 | size_t size, size_t align, unsigned long flags) |
1629 | { | 1629 | { |
1630 | size_t left_over = 0; | 1630 | size_t left_over = 0; |
1631 | int gfporder; | ||
1631 | 1632 | ||
1632 | for (;; cachep->gfporder++) { | 1633 | for (gfporder = 0 ; gfporder <= MAX_GFP_ORDER; gfporder++) { |
1633 | unsigned int num; | 1634 | unsigned int num; |
1634 | size_t remainder; | 1635 | size_t remainder; |
1635 | 1636 | ||
1636 | if (cachep->gfporder > MAX_GFP_ORDER) { | 1637 | cache_estimate(gfporder, size, align, flags, &remainder, &num); |
1637 | cachep->num = 0; | ||
1638 | break; | ||
1639 | } | ||
1640 | |||
1641 | cache_estimate(cachep->gfporder, size, align, flags, | ||
1642 | &remainder, &num); | ||
1643 | if (!num) | 1638 | if (!num) |
1644 | continue; | 1639 | continue; |
1640 | |||
1645 | /* More than offslab_limit objects will cause problems */ | 1641 | /* More than offslab_limit objects will cause problems */ |
1646 | if (flags & CFLGS_OFF_SLAB && cachep->num > offslab_limit) | 1642 | if ((flags & CFLGS_OFF_SLAB) && num > offslab_limit) |
1647 | break; | 1643 | break; |
1648 | 1644 | ||
1645 | /* Found something acceptable - save it away */ | ||
1649 | cachep->num = num; | 1646 | cachep->num = num; |
1647 | cachep->gfporder = gfporder; | ||
1650 | left_over = remainder; | 1648 | left_over = remainder; |
1651 | 1649 | ||
1652 | /* | 1650 | /* |
1653 | * Large number of objects is good, but very large slabs are | 1651 | * Large number of objects is good, but very large slabs are |
1654 | * currently bad for the gfp()s. | 1652 | * currently bad for the gfp()s. |
1655 | */ | 1653 | */ |
1656 | if (cachep->gfporder >= slab_break_gfp_order) | 1654 | if (gfporder >= slab_break_gfp_order) |
1657 | break; | 1655 | break; |
1658 | 1656 | ||
1659 | if ((left_over * 8) <= (PAGE_SIZE << cachep->gfporder)) | 1657 | /* |
1660 | /* Acceptable internal fragmentation */ | 1658 | * Acceptable internal fragmentation? |
1659 | */ | ||
1660 | if ((left_over * 8) <= (PAGE_SIZE << gfporder)) | ||
1661 | break; | 1661 | break; |
1662 | } | 1662 | } |
1663 | return left_over; | 1663 | return left_over; |