aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mm/slab.c48
1 files changed, 27 insertions, 21 deletions
diff --git a/mm/slab.c b/mm/slab.c
index b264214c77ea..f81176dd0a90 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -565,9 +565,31 @@ static inline struct array_cache *cpu_cache_get(struct kmem_cache *cachep)
565 return cachep->array[smp_processor_id()]; 565 return cachep->array[smp_processor_id()];
566} 566}
567 567
568static size_t slab_mgmt_size(size_t nr_objs, size_t align) 568static int calculate_nr_objs(size_t slab_size, size_t buffer_size,
569 size_t idx_size, size_t align)
569{ 570{
570 return ALIGN(nr_objs * sizeof(unsigned int), align); 571 int nr_objs;
572 size_t freelist_size;
573
574 /*
575 * Ignore padding for the initial guess. The padding
576 * is at most @align-1 bytes, and @buffer_size is at
577 * least @align. In the worst case, this result will
578 * be one greater than the number of objects that fit
579 * into the memory allocation when taking the padding
580 * into account.
581 */
582 nr_objs = slab_size / (buffer_size + idx_size);
583
584 /*
585 * This calculated number will be either the right
586 * amount, or one greater than what we want.
587 */
588 freelist_size = slab_size - nr_objs * buffer_size;
589 if (freelist_size < ALIGN(nr_objs * idx_size, align))
590 nr_objs--;
591
592 return nr_objs;
571} 593}
572 594
573/* 595/*
@@ -600,25 +622,9 @@ static void cache_estimate(unsigned long gfporder, size_t buffer_size,
600 nr_objs = slab_size / buffer_size; 622 nr_objs = slab_size / buffer_size;
601 623
602 } else { 624 } else {
603 /* 625 nr_objs = calculate_nr_objs(slab_size, buffer_size,
604 * Ignore padding for the initial guess. The padding 626 sizeof(unsigned int), align);
605 * is at most @align-1 bytes, and @buffer_size is at 627 mgmt_size = ALIGN(nr_objs * sizeof(unsigned int), align);
606 * least @align. In the worst case, this result will
607 * be one greater than the number of objects that fit
608 * into the memory allocation when taking the padding
609 * into account.
610 */
611 nr_objs = (slab_size) / (buffer_size + sizeof(unsigned int));
612
613 /*
614 * This calculated number will be either the right
615 * amount, or one greater than what we want.
616 */
617 if (slab_mgmt_size(nr_objs, align) + nr_objs*buffer_size
618 > slab_size)
619 nr_objs--;
620
621 mgmt_size = slab_mgmt_size(nr_objs, align);
622 } 628 }
623 *num = nr_objs; 629 *num = nr_objs;
624 *left_over = slab_size - nr_objs*buffer_size - mgmt_size; 630 *left_over = slab_size - nr_objs*buffer_size - mgmt_size;